题目描述:
有 n 头牛(1<=n<=50000)要挤奶。给定每头牛挤奶的时间区间 [A,B] (1<=A<=B<=1000000,A,B 为整数)。牛需要呆畜栏里才能挤奶。一个畜栏同一时间只能容纳一头牛。问至少需要多少个畜栏,才能完成全部挤奶工作,以及每头牛都放哪个畜栏里(Special judged)
去同一个畜栏的两头牛,它们挤奶时间区间哪怕只在端点重合也是不可以的
输入:
第 1 行:单个整数 N,表示一共多少头牛
第 2 行到 N + 1 行,每行两个整数,表示每头奶牛的挤奶时间间隔
输出:
一共需要多少个畜栏,每头奶牛应该放在哪个畜栏中
Sample Input
5
1 10
2 4
3 6
5 8
4 7
Sample Output
4
1
2
3
2
4
别人的思路:
我们来说说这题吧, 这是一道优先队列加上贪心的题目,主要是贪心。
我们首先按照奶牛的挤奶需求,把它们的挤奶时间按照挤奶的开始时间,从早到晚的顺序进行排列。然后我们就开始给它们分配畜栏。
我们认定每个奶牛都有一个序号,我们读入的时候,就给它从1到n-1写入它的序号里面。
分配的过程是这样的:
如果畜栏队列为空,我们就给它直接分配一个畜栏,将总共的畜栏序号++,然后把这头奶牛所放入的畜栏序号,就是当今的畜栏总号,填入pos数组,下标是奶牛的编号。
我们修改这个畜栏的结束时间,改成奶牛挤奶的结束时间,畜栏的序号也改成总的畜栏序号,之后压入优先队列。
如果畜栏队列不为空,就说明此时已经分配了畜栏,如果此时最早结束使用的畜栏,它的结束时间早于这头奶牛挤奶的开始时间,那我们就可以把这头奶牛放入这头畜栏。
我们把这个畜栏弹出优先队列,因为下一次压入之后的结束时间就改变了。
我们修改这个畜栏的结束时间为奶牛挤奶的结束时间,畜栏的序号不变。奶牛 i 的pos数组对应的位置修改成畜栏的序号,将畜栏压入优先队列。
如果最早结束的都不能满足的话,我们就重新给它分配一个畜栏,重复之前的队列为空的流程。
代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
struct Cow
{
int start,end;
int num;
bool operator < (const Cow &b)const
{
return start<b.start;
}
}cow[50050];
int pos[50050];
struct Stall
{
int end;
int num;
bool operator < (const Stall &b)const
{
return end>b.end;
}
Stall(int a,int b):end(a),num(b){}
};
int main()
{
int n;
scanf("%d",&n);
for (int i=0;i<n;i++)
{
scanf("%d%d",&cow[i].start,&cow[i].end);
cow[i].num=i;
}
sort(cow,cow+n);
int total=0;
priority_queue<Stall>pq;
for (int i=0;i<n;i++)
{
if (pq.empty())
{
total++;
pos[cow[i].num]=total;
pq.push(Stall(cow[i].end,total));
}
else {
Stall st=pq.top();//结束时间最早的畜栏
if (st.end<cow[i].start)
{
pq.pop();
pos[cow[i].num]=st.num;
pq.push(Stall(cow[i].end,st.num));
}
else
{
total++;
pos[cow[i].num]=total;
pq.push(Stall(cow[i].end,total));
}
}
}
printf("%d\n",total);
for (int i=0;i<n;i++)
{
printf("%d\n",pos[i]);
}
return 0;
}
我学到的:
大意就是:放牛进栏杆,到时间再放出来,有牛就放,若有其他牛到时间,出来时,就放进那头牛的栏杆中,否则新放个栏杆
1571

被折叠的 条评论
为什么被折叠?



