4144.畜栏保留问题【贪心+优先队列】

4144.畜栏保留问题总时间限制: 1000ms 内存限制: 65536kB描述农场有N头牛,每头牛会在一个特定的时间区间[A, B](包括A和B)在畜栏里挤奶,且一个畜栏里同时只能有一头牛在挤奶。现在农场主希望知道最少几个畜栏能满足上述要求,并要求给出每头牛被安排的方案。对于多种可行方案,主要输出一种即可。输入输入的第一行包含一个整数N(1 ≤ N ≤ 50, 000),表示有N牛头;接下来N行每行包含两个数,分别表示这头牛的挤奶时间[Ai, Bi](1 ≤ A≤ B ≤ 1, 000, 000
摘要由CSDN通过智能技术生成

4144.畜栏保留问题

总时间限制: 1000ms 内存限制: 65536kB

描述

农场有N头牛,每头牛会在一个特定的时间区间[A, B](包括A和B)在畜栏里挤奶,且一个畜栏里同时只能有一头牛在挤奶。现在农场主希望知道最少几个畜栏能满足上述要求,并要求给出每头牛被安排的方案。对于多种可行方案,主要输出一种即可。

输入

输入的第一行包含一个整数N(1 ≤ N ≤ 50, 000),表示有N牛头;接下来N行每行包含两个数,分别表示这头牛的挤奶时间[Ai, Bi](1 ≤ A≤ B ≤ 1, 000, 000)。

输出

输出的第一行包含一个整数,表示最少需要的畜栏数;接下来N行,第i+1行描述了第i头牛所被分配的畜栏编号(从1开始)。

样例输入

5
1 10
2 4
3 6
5 8
4 7

样例输出

4
1
2
3
2
4

分析

贪心策略

最大限度利用已有的畜栏。

  1. 把n头牛按照开始时间排序;
  2. 为第1头牛新建一个畜栏,记录其结束时间;
  3. 对于第i头牛,找到已有的畜栏中结束时间最早的,并与它自己的开始时间比较。
  4. 如果开始时间大于(注意这里是严格大于,之前自以为是大于等于然后一直WA嘤嘤嘤┭┮﹏┭┮)最早的结束时间,就把牛i安排到那个畜栏里面,把原来的牛j“丢出来”;如果小于等于,就新建一个畜栏。更新结束时间。

贪心策略正确性的证明

假设用以上贪心策略对前n头牛的安排方案至少和最优策略用的畜栏数相同,并且该方案具有最小的最早结束时间。

  1. 当n=1时,结论显然成立;
  2. 假设当n=k时也成立,那么对于k+1头牛:
    ① 证明贪心策略对前n头牛的安排方案至少和最优策略用的畜栏数相同:
    (反证法)若畜栏数不是最优的,已知k头牛的最优策略的畜栏数就是上述贪心策略得到的,那么前k+1头牛的最优策略不会小于这个数;
    又因为结论不成立,所以一定是——
    贪心策略:放入第k+1头牛的时候,它的开始时间Ak+1小于前k头牛贪心策略得到的最早结束时间Tk,新建了一个畜栏;
    最优策略:放入第k+1头牛的时候,它的开始时间大于等于前k头牛最优策略得到的最早结束时间T’k,放入了已有的畜栏;
    也就是T’k<=Ak+1<Tk——这与归纳假设中前k头牛的贪心策略具有最小的最早结束时间矛盾!
    ② 证明贪心策略具有最小的最早结束时间:
    当第k+1头牛的开始时间小于最小的最早结束时间,就新建一个畜栏,这是最早结束时间更新为第k+1头牛的结束时间(如果它比原有的更小),或者保持原来的最小最早结束时间不变;
    否则,放入相应的畜栏,在所有的畜栏的结束时间中找到最小的,更新最早结束时间。
    上述每一种更新,都保证了最早的结束时间是最小的。

贪心的实现

  1. 按照开始时间排序所有的牛;
  2. 用优先队列维护已有畜栏,保证堆顶的畜栏具有最小的最早结束时间;
    对于一头新的牛,要么把原有的牛弹出,再放入自己(相当于更新了原有的畜栏的状态),要么直接放入自己(相当于新建了一个畜栏)。
  3. 注意此时的运算符重载在结构体内部

代码及解析

#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 50010
struct cattle//定义结构体,l,r分别表示牛挤奶的开始、结束时间,id表示第i头牛
{
   
	int l
  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值