0%

「USACO06FEB」Stall Reservations

题目链接 & 题面

貌似是 USACO 原创,但我实在找不到原创的链接,只能在洛谷、 AcWing 和 POJ 上找了

洛谷:https://www.luogu.com.cn/problem/P2859

AcWing:https://www.acwing.com/problem/content/113/

题目描述

有N头牛在畜栏中吃草。

每个畜栏在同一时间段只能提供给一头牛吃草,所以可能会需要多个畜栏。

给定N头牛和每头牛开始吃草的时间A以及结束吃草的时间B,每头牛在[A,B]这一时间段内都会一直吃草。

当两头牛的吃草区间存在交集时(包括端点),这两头牛不能被安排在同一个畜栏吃草。

求需要的最小畜栏数目和每头牛对应的畜栏方案。

输入格式

第1行:输入一个整数N。

第2…N+1行:第i+1行输入第i头牛的开始吃草时间A以及结束吃草时间B,数之间用空格隔开。

输出格式

第1行:输入一个整数,代表所需最小畜栏数。

第2…N+1行:第i+1行输入第i头牛被安排到的畜栏编号,编号是从1开始的 连续 整数,只要方案合法即可。

(洛谷上题目描述是挤奶,AcWing上是吃草。。。)

基本算法

贪心

应该是比较显而易见的一个贪心,我刚开始都不觉得自己有多贪。。

按开始的时间把牛排序,然后依次放入畜栏,每次尽量放在已经使用过的畜栏中,如果没有就新建一个畜栏,cnt++。

由于可以放进任意一个畜栏,可以直接选出结束时间最早的畜栏比较,如果比当前时间早就可以放入,如果比当前时间晚就新建。

因此,可以通过 std::priority_queue 来维护一个小根堆来存放畜栏使用情况(当然手写也可以

priority_queue

我一般管这个叫优先队列,它可以保证队头的元素是 最小/最大 的。

对于这道题,存放畜栏的优先队列需要存放 畜栏中牛结束的时间 和 畜栏的编号,其中需要将最小值放在队首的是结束时间。因此,可以使用 std::pair 来作为一个单位存放。对于 pair ,每个元素进行比较时,先比较 first ,所以可以把结束时间放在 first 中。

当然,手写一个node然后重载运算符来自定义比较也可以,但这就是 C++ 的进阶操作了。

另外,在写的时候,一定要搞清楚队列里要存什么,思路一定要清晰(我就是因为这个被绕住了)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <functional>
using std::priority_queue;
using std::vector;
using std::sort;
using std::greater;
typedef std::pair<int,int> pint;

const int MAX=50005;
int n, cnt, le, ans[MAX];
priority_queue < pint, vector<pint>, greater<pint> > cl;
pint tmp;
struct Cow{
int start, end, nu;
}cow[MAX];

bool cmp(Cow x, Cow y) { return x.start < y.start; }

int main(){
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);

scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%d %d", &cow[i].start, &cow[i].end);
cow[i].nu=i;
}
sort(cow, cow+n, cmp);
for(int i=0; i<n; i++){
if(!cl.empty() && cl.top().first<cow[i].start){
ans[cow[i].nu]=cl.top().second;
cl.pop();
tmp.first=cow[i].end; // tmp.second=cl.size();
tmp.second=ans[cow[i].nu];
cl.push(tmp);

}
else{
cnt++;
tmp.first=cow[i].end; tmp.second=cnt;
cl.push(tmp);
ans[cow[i].nu]=cnt;
}
}
printf("%d\n", cnt);
for(int i=0; i<n; i++) printf("%d\n", ans[i]);

return 0;
}