(不易)POJ-3190 區間貪心
阿新 • • 發佈:2019-01-23
題目大意:一些奶牛要在指定的時間內擠牛奶,而一個機器只能同時對一個奶牛工作。給你每頭奶牛的指定時間的區間,問你最小需要多少機器。
分析:先按開始時間從早到晚對區間排序(記為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; }