1. 程式人生 > >(不易)POJ-3190 區間貪心

(不易)POJ-3190 區間貪心

題目大意:一些奶牛要在指定的時間內擠牛奶,而一個機器只能同時對一個奶牛工作。給你每頭奶牛的指定時間的區間,問你最小需要多少機器。

分析:先按開始時間從早到晚對區間排序(記為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;
}