所谓贪心: 就是只管当下的最优解。
下面看 一个例题:
此例题来自洛谷 P2859 [USACO06FEB]Stall Reservations S;
下面看题目:
解题思路:
每头奶牛的开始与结束时间 可以看成一个线段;求解当下线段重合部分的最大值;
#include<bits/stdc++.h>
using namespace std;
struct COW {
int begin,end;
int id; // 为每一个奶牛编号,方便最后被打乱顺序之后恢复原样
int used_in_which; //奶牛用过的牛棚的编号
}cow[50004];
bool cmp(COW a,COW b){
return a.begin < b.begin;
}
bool cmp1(COW a, COW b) {
return a.id < b.id;
}
priority_queue <pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>> >q;
// 前置知识:: pari的比较,先比较第一个元素,第一个相等比较第二个.
// 优先队列 : 先以结束时间进行比较 结束时间小的排前面; 如果结束时间 一样 比较 围栏的数量 围栏小的 排前面.
int main() {
int n = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d%d", &cow[i].begin, &cow[i].end);
cow[i].id = i ;// 为每一个奶牛编号,方便最后被打乱顺序之后恢复原样.
}
sort(cow, cow + n, cmp); // 进行排序 : 以开始时间开始排升序.
cow[0].used_in_which = 1; // 第一头奶牛直接 开一个 围栏.
int tot = 1; // 围栏的总数.
q.push(make_pair(cow[0].end, tot)); // 输入第一头奶牛的结束时间.
for (int i = 1; i < n; i++) {
int x = q.top().first; // 取优先(升序)队列的 首元素.
int cur_id = q.top().second; // 取 首奶牛的 栅栏序号
if (cow[i].begin > x) { // 如果 第 i 头奶牛的 开始时间 大于 排在 优先队列首元素的结束时间 那么就可以进行无缝衔接,直接继承.
q.pop(); // 进来之后 首元素的用处就没有了 进行 Pop.
q.push(make_pair(cow[i].end,cur_id)); // 推入新的奶牛的 结束时间, 以及栅栏序号.
cow[i].used_in_which = cur_id; // ** 记录第 i 头 奶牛的栅栏编号
}
else {
tot++; // 如果 第 i 头 奶牛的开始时间 小于 排在优先队列首元素的结束时间 那么 需要新开一个栅栏.
cow[i].used_in_which = tot; // 第 i 头 奶牛的栅栏位置 就为 新的 tot.
q.push(make_pair(cow[i].end,tot)); // 推入新的奶牛的 结束时间, 以及栅栏序号.
}
}
// 接下来进行打印;
printf("%d\n", tot);
sort(cow, cow + n, cmp1);
for (int i = 0; i < n; i++) {
printf("%d\n", cow[i].used_in_which);
}
return 0;
}