贪心算法
活动安排问题算是典型的贪心问题了, 而且也和生活紧密联系.
活动安排问题有两种非常相近的形式, 贪的方法也很相似.
因为之前做过期中一个问题, 做第二种问题时转不过思维来, 卡在那不知道怎么做.
手动模拟的时候, 突然明白过来, 靠, 原来是这样!!!
先分析第一题:
有若干个活动,第i个开始时间和结束时间是[Si,fi),只有一个教室, 请问最多可以安排多少个活动?
思路:
把它的fi排序, 然后从小到大遍历可能的活动. 结果就是最大的活动数.
这题比较简单, 不提供代码
分析第二题:
有若干个活动,第i个开始时间和结束时间是(Si,fi),同一个教室安排的活动之间不能交叠,求要安排所有活动,最少需要几个教室?
这道题思考了很久, 就是不知道怎么贪心最好.
试着用第一题的思路, 每次把剩余的活动加入到教室, 直到没有活动为止, 看用了多少个教室.
思路是:
把每一个活动时间接到结束时间最近的时间序列(教室数), 不能接就另开新行.
具体理解还要做一做图模拟模拟.
代码
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
struct th {int s, e; } arr[10005];
bool cmp(th x, th y) {return x.s < y.s;}
int main()
{
int n;
cin >> n;
priority_queue<int,vector<int>, greater<int> > myqueue;
for(int i = 0; i < n; ++i) {
cin >> arr[i].s >> arr[i].e;
}
sort(arr, arr+n, cmp);
int ans = 1;
myqueue.push(arr[0].e);
for(int i = 1; i < n; ++i) {
if(arr[i].s < myqueue.top()) {
ans++;
myqueue.push(arr[i].e);
} else {
myqueue.pop();
myqueue.push(arr[i].e);
}
}
cout << ans;
}
/*
4
1 3
2 5
3 4
6 8
*/
这个代码中使用了优先队列, 默认的优先队列是大的优先级最大, 此例可以调整.
priority_queue< int,vector, greater > myqueue; //从小到大
priority_queue< int,vector, less > myqueue; //从大到小(默认)
int 是可换的。
至于这道题问什么这么贪心,改变顺序分析一下,会发现不会有更优解。