贪心算法
选择当前看来最好的解,局部上的最优解。适合最优子结构,即大问题的最优解包含子问题的最优解
求解蓄栏保留问题
农场里有n头牛,每头牛会有一个特定的时间区间[a,b]在蓄栏利挤牛奶,并且一个栏内任何时刻只能有一头牛挤奶,求最少蓄栏能够满足上述要求,并给出安排方案
解:设牛的编号1-n,活动的时间是闭区间,不能重复,所以将所有活动排序:结束时间相同按开始时间递增排序,否则按时间结束时间递减排序。
找出一个最大兼容活动子集,个数就是最少蓄栏的个数。
i | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
开始时间 | 1 | 2 | 5 | 8 | 4 | 12 | 11 |
结束时间 | 4 | 5 | 7 | 9 | 10 | 13 | 15 |
1 | 3 | 4 | 6 |
---|---|---|---|
1 | 2 | 8 | 12 |
4 | 7 | 9 | 13 |
这是一个最大兼容活动子集,同样2、7是一个子集,5又是一个自己,最大兼容活动子集个数为3
// 问题表示
struct Cow //奶牛的类型声明
{ int no;//编号
int b;//起始时间
int e;//结束时间
bool operator<(const Cow &s) const //重载关系函数
{ if(e==s.e) //结束时间相同按开始时间递增排序
return b<= s.b;
else
return e<=s.e; //否则按结束时间递减排序
}
};
int ans[MAX]; //表示结果,ans[i]表示第A[i].no头牛的蓄栏编号
int n=5;
Cow A[]={{0},{1,1,10},{2,2,4},{3,3,6},{4,5,8},{5,4,7}};
// 求解最大兼容活动子集个数
void solve()
{ sort(A+1,A+n+1);
memset(ans,0,sizeof(ans));
int num=1;
for(int i=1;i<=n;i++)
{ if (ans[i]==0) //第i头牛没有安排蓄栏
{ ans[i]=num; //给他安排num
int preend=A[i].e; //前一个兼容活动结束时间
for(int j=i+1;j<=n;j++)
{ if(A[j].b>preend && ans[j]=0)
{ ans[j]=num; //将兼容活动子集中活动安排在num蓄栏中
preend=A[j].e; //更新结束时间
}
}
num++; //查找下一个最大兼容活动子集,num+1
}
}
}