(不易)POJ-3190 区间贪心

来源:互联网 发布:php招聘要求 编辑:程序博客网 时间:2024/05/22 15:12

题目大意:一些奶牛要在指定的时间内挤牛奶,而一个机器只能同时对一个奶牛工作。给你每头奶牛的指定时间的区间,问你最小需要多少机器。


题目链接:点击打开链接


分析:先按开始时间从早到晚对区间排序(记为cow[]),然后维护一个优先队列,优先权大的为结束时间早的。优先队列中的每一个区间都代表一台机器正在运行的时间。然后扫描一遍cow,当检查cow[i]时,判断优先队列中的top元素的结束时间是否小于cow[i]的开始时间。

如果是,则说明这台机器可以供cow[i]一起使用(假设这台机器编号为1),那么如果机器2的结束时间也小于cow[i]的开始时间,那么使用机器2是否会比机器1更优呢?举个实例,假设现在机器1的区间为[1,4],机器2的区间为[2,7],cow[i]的区间为[8,10],如果使用机器1,由于cow[i]之后的cow[i+k](k>0)的开始时间一定大于8,所以机器1空闲的[5,7]这段时间肯定是不会被用到(即不会被浪费,因为你只能选择浪费,就好像你有100元却只有50元的东西让你买,最终反正得浪费50),所以并不会影响其达到最优,当然使用机器2也是最优。可是如果选择机器2那么答案肯定会错,因为这是题中数据确定的。。。虽然我也不明白这是为啥,但选机器1肯定也是最优。于是将cow[i]加入优先队列中,且除掉top,并且记下cow[i]使用的是哪台机器(可由top使用的机器的编号确定)。

如果不是,则队列中肯定不存在结束时间小于cow[i]的开始时间的机器了,于是此时便需要启动一台新的机器,所以ans++,然后将cow[i]入队,并记其使用的机器编号为ans。


附上代码:

#include<algorithm>#include<iostream>#include<queue>using namespace std;struct Cow{int x, y;int id;Cow(int a = 0, int b = 0, int c = 0){ x = a, y = b, id = c; }bool operator <(const Cow &c)const { return y>c.y; }}cow[50000 + 5];int prv[50000 + 5];               //prv[i]表示第i个输入的牛所使用的机器的编号int n, ans;priority_queue<Cow> q;bool cmp(const Cow &a, const Cow &b){ return a.x < b.x; }      int main(){scanf("%d", &n);for (int i = 1; i <= n; i++){scanf("%d%d", &cow[i].x, &cow[i].y);cow[i].id = i;                          //按输入顺序记下序号}sort(cow + 1, cow + n + 1, cmp);ans = 1;q.push(cow[1]);prv[cow[1].id] = 1;for (int i = 2; i <= n; i++){Cow t = q.top();if (cow[i].x > t.y){q.push(cow[i]);prv[cow[i].id] = prv[t.id];q.pop();}else{ans++;q.push(cow[i]);prv[cow[i].id] = ans;}}printf("%d\n", ans);for (int i = 1; i <= n; i++)printf("%d\n", prv[i]);return 0;}


0 0