(不易)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;
}


你可能感兴趣的:(ACM,区间贪心,题解报告)