您的位置:首页 > 其它

贪心算法的例子:活动选择问题

2018-04-06 14:52 260 查看

贪心算法的例子

标签(空格分隔): 算法知识文档 贪心算法

活动选择问题

输入:

nn项活动.S={1,2,3,...,n}S={1,2,3,...,n}项活动的集合,si,fisi,fi 分别为活动 ii的开始和结束时间.

定义: 活动ii和jj相容,当且仅当fj≤sifj≤si或者fi≤sjfi≤sj,也就是活动i,ji,j没有公共的时间交叉.

求:

最大的两两相容的活动集合AA,当前的活动最大结束时间TT

输入实例:

ii12345678910
sisi1325456882
fifi45679910111213
人工求解: A={1,4,8},T=11A={1,4,8},T=11

贪心算法:

描述:

挑选过程是多步判断,每步依据某种”短视”的策略进行活动选择,选择的时候注意满足相容的条件.所谓”短视”就是只关注眼前来进行决策.

策略一:

开始时间早的优先排序使得s1≤s2≤...≤sns1≤s2≤...≤sn,从前向后挑选.

策略二:

占用时间少的优先排序使得f1−s1≤f2−s2≤...≤sn−fnf1−s1≤f2−s2≤...≤sn−fn,从前向后挑选.

策略三:

结束时间早的优先,排序使得f1≤f2≤...≤fnf1≤f2≤...≤fn,从前向后挑选.

策略一的反例:

策略一: 开始早的优先

反例:n=3,S=1,2,3n=3,S=1,2,3

s1=0,f1=20,s2=2,f2=5,s3=8,f3=15s1=0,f1=20,s2=2,f2=5,s3=8,f3=15

如果按照这个策略那么得到的结果是A={1},T=20A={1},T=20,但是我们很容易知道最优的解应该是使得|A||A|最大,那么当A={2,3},T=15A={2,3},T=15,满足两两互不相容的最优解.

策略二的反例:

策略二: 占时间少的优先

反例:n=3,S=1,2,3n=3,S=1,2,3

s1=0,f1=8,s2=7,f2=9,s3=8,f3=15s1=0,f1=8,s2=7,f2=9,s3=8,f3=15

利用此策略得到的解是A={2},T=9A={2},T=9,但是最优解应该是A={1,3},T=15A={1,3},T=15

策略三是正确的:

因为不会进行数学证明,所以举不出反例它就是对的.

CODE:CODE:

#include <bits/stdc++.h>

using namespace std;

#define MAX_N 1000005 // 最大活动数目
int n;
typedef struct Action{
int i; // 活动编号
int s,f; // 开始和结束时间
}Action;

Action S[MAX_N]; // 活动集合
int cur,A[MAX_N],T; // 当解集合下标位置,A,T是解

// 按照结束时间早的排序
bool cmp(Action a, Action b){
return a.f < b.f;
}

void printAns(){
int i,j;
printf("A =");
for(i = 1; i <= cur; i++) printf("%d  ", A[i]);
printf("\nT = %d\n\n", T);
}

// 贪心
void solve(){
int i;
// 按照结束时间早的排序
sort(S+1, S+n+1, cmp);
A[cur] = S[1].i;
T = S[1].f; // 最后选择的活动的结束时间
for(i = 2; i <= n; i++){
if(S[i].s >= T) { // 满足条件的活动
A[++cur] = S[i].i;
T = S[i].f; // 更新f
}
}
printAns(); // 打印结果
}

int main(){
//freopen("in.txt", "r", stdin);
int i;
while(~scanf("%d", &n) && n){ // 输入数据
cur = 1;
for(i = 1; i <= n; i++) {
scanf("%d%d", &S[i].s, &S[i].f);
S[i].i = i;
}
solve();
}
return 0;
}


输入:

10

1 4

3 5

2 6

5 7

4 9

5 9

6 10

8 11

8 12

2 13

3

0 20

2 5

8 15

3

0 8

7 9

8 15

输出:

A =1 4 8

T = 11

A =2 3

T = 15

A =1 3

T = 15

算法时间复杂度: 排序+选择: O(nlogn)+O(n)=O(nlogn)O(nlog⁡n)+O(n)=O(nlog⁡n)

贪心算法的特点:

t贪心法适用于组合优化问题

求解过程是多步判断过程,最终的判断序列对应于问题的最优解.

依据某种”短视”的贪心选择性质判断,性质好坏决定算法的成败.

贪心法必须进行正确性的证明

证明贪心法策略不正确的技巧:取反例.

@author 何军
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: