贪心算法的例子:活动选择问题
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
输入实例:
ii | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
sisi | 1 | 3 | 2 | 5 | 4 | 5 | 6 | 8 | 8 | 2 |
fifi | 4 | 5 | 6 | 7 | 9 | 9 | 10 | 11 | 12 | 13 |
贪心算法:
描述:挑选过程是多步判断,每步依据某种”短视”的策略进行活动选择,选择的时候注意满足相容的条件.所谓”短视”就是只关注眼前来进行决策.
策略一:
开始时间早的优先排序使得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(nlogn)+O(n)=O(nlogn)
贪心算法的特点:
t贪心法适用于组合优化问题求解过程是多步判断过程,最终的判断序列对应于问题的最优解.
依据某种”短视”的贪心选择性质判断,性质好坏决定算法的成败.
贪心法必须进行正确性的证明
证明贪心法策略不正确的技巧:取反例.
@author 何军