POJ 3190 Stall Reservations 贪心+优先队列

Description
Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will only be milked over some precise time interval A…B (1 <= A <= B <= 1,000,000), which includes both times A and B. Obviously, FJ must create a reservation system to determine which stall each cow can be assigned for her milking time. Of course, no cow will share such a private moment with other cows.
Help FJ by determining:
The minimum number of stalls required in the barn so that each cow can have her private milking period
An assignment of cows to these stalls over time
Many answers are correct for each test dataset; a program will grade your answer.
Input
Line 1: A single integer, N
Lines 2…N+1: Line i+1 describes cow i’s milking interval with two space-separated integers.
Output
Line 1: The minimum number of stalls the barn must have.
Lines 2…N+1: Line i+1 describes the stall to which cow i will be assigned for her milking period.
Sample Input
5
1 10
2 4
3 6
5 8
4 7
Sample Output
4
1
2
3
2
4
Hint
Explanation of the sample:
Here’s a graphical schedule for this output:
Time 1 2 3 4 5 6 7 8 9 10
Stall 1 c1>>>>>>>>>>>>>>>>>>>>>>>>>>>
Stall 2 … c2>>>>>> c4>>>>>>>>> … …
Stall 3 … … c3>>>>>>>>> … … … …
Stall 4 … … … c5>>>>>>>>> … … …
Other outputs using the same number of stalls are possible. (该题目存在特殊判题)

题目大意:
每头奶牛拥有自己的挤奶区间,而它们又不愿意在同一个畜栏中(即两头奶牛的挤奶区间不能重合,端点重合也不允许),求最小畜栏数和每头牛吃的栏编号。

解题思路:
可以用贪心做,依据奶牛挤奶区间的开始时间排序。依次放奶牛,若所有畜栏都没空,那么就再造一个畜栏。

一开始写了个n^2 暴力统计,预想会超时,果真就超时了。。。
然后查看大佬们的思路发现可以用优先队列进行优化(结束时间早的畜栏优先度高),那么时间复杂度就降为O(nlogn)然后就可以过了

下面来探讨一下为什么结束时间早的畜栏优先度高:
1、如果现在要考虑的奶牛挤奶区间为New1,则能够选择的已有畜栏只有栏一;
2、如果现在要考虑的奶牛挤奶区间为New2,则三个已有畜栏都可以选择,此时选择任何一个都可以,因为已经依据奶牛挤奶区间的开始时间进行排序,所以接下来要考虑的区间左边界一定不大于New2的左边界,因此无论选择哪一个,三种情况下对于接下来的选择都是等价的。故而我们可以认为结束时间早的畜栏优先度高以方便讨论。
在这里插入图片描述
AC代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
struct node {
	int x, y;
	int t, myself;
	bool operator < (const node &a) const {//优先队列,大顶堆,重载运算符以便强行输出最小
		if (y == a.y) { return x > a.x; }
		return y > a.y;
	}
}list[50001];
priority_queue<node> que;
bool cmp1(node a, node b) {
	if (a.x == b.x) { return a.y < b.y; }
	return a.x < b.x;
};
bool cmp2(node a, node b) {
	return a.myself < b.myself;
};
int main() {
	int n;
	while (scanf("%d", &n) != EOF) {
		for (int i = 1; i <= n; i++) {
			scanf("%d%d", &list[i].x, &list[i].y);
			list[i].t = 0; list[i].myself = i;
		}
		sort(list + 1, list + 1 + n, cmp1);
		int ans = 1;
		list[1].t = ans;
		que.push(list[1]);
		for (int i = 2; i <= n; i++) {
			if (list[i].x > que.top().y) {
				list[i].t = que.top().t;
				que.pop();
				que.push(list[i]);
			}
			else {
				ans++;
				list[i].t = ans;
				que.push(list[i]);
			}
		}
		printf("%d\n", ans);
		sort(list + 1, list + 1 + n, cmp2);
		for (int i = 1; i <= n; i++) {
			printf("%d\n", list[i].t);
		}
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值