畜栏保留问题
- 总时间限制:
- 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) 把所有奶牛按开始时间从小到大排序。
2) 为第一头奶牛分配一个畜栏。
3) 依次处理后面每头奶牛i。处理 i 时,考虑已分配畜栏中,结束时间最早的畜栏x。
若 E(x) < S(i), 则不用分配新畜栏,i可进入x,并修改E(x)为E(i)若 E(x) >= S(i),则分配新畜栏y,记 E(y) = E(i)
直到所有奶牛处理结束
需要用优先队列存放已经分配的畜栏,并使得结束时间最早的畜栏始终 位于队列头部。
这里第搜索畜栏有没有空的,最好使用STL中的优先队列,这样时间复杂度才是nlogn,这样才能勉强过;
ps:在poj上c++编译能过,g++不能过;
#include<iostream>
#include <queue>
using namespace std;
#define NUM 50005
struct cow{
int f;
int e;//挤奶区间起终点
int NO;//编号
bool operator<(const struct cow &t) const{
return this->f<t.f;
}
}Cow[NUM];
int result[NUM];//表示编号为i的奶牛去的畜栏编号
struct Fence
{
int k;//开始
int j;//结束
int NO;//栅栏编号;
bool operator<(const Fence &t)const{
return this->j>t.j;//先用时间结束晚的;
}
Fence(){};
Fence(int x,int y,int n):k(x),j(y),NO(n){}
};
int main()
{
int N;
cin>>N;
for(int i = 0;i<N;i++)
{cin>>Cow[i].f>>Cow[i].e; Cow[i].NO = i;}
// for(int i = 0;i<N;i++)
// {cout <<Cow[i].f<<" "<<Cow[i].e<<" "<< Cow[i].NO<<endl;}
sort(Cow, Cow+N);
// for(int i = 0;i<N;i++)
// {cout <<Cow[i].f<<" "<<Cow[i].e<<" "<< Cow[i].NO<<endl;}
int totle = 0;
priority_queue<Fence > pq;
for(int i = 0;i<N;i++){
if(pq.empty()){
totle++;
pq.push(Fence(Cow[i].f,Cow[i].e,totle));
result[Cow[i].NO] = totle;
}
else{
Fence tt = pq.top();
if(tt.j<Cow[i].f){
pq.pop();
result[Cow[i].NO] = tt.NO;
pq.push(Fence(Cow[i].f,Cow[i].e,tt.NO));
}
else{
totle++;
pq.push(Fence(Cow[i].f,Cow[i].e,totle));
result[Cow[i].NO] = totle;
}
}
}
cout <<totle<<endl;
for(int i = 0;i < N;++i)
cout <<result[i]<<endl;
return 0;
}