题目链接:http://poj.org/problem?id=3190
花了好长时间卡了很久,在贵人的指点下终于过了。
题目大意:有n头牛,每头牛都有特定的取奶时间段且相互之间不能有重叠,取奶场所为畜栏,现在要给所有乳牛取奶,要求求出最少的畜栏数并列出每头牛对应的畜栏位置。
思路:先以开始时间小到大排序,用当前最早开始的结束时间为新的扩充起点,继续往下找开始时间比它晚的。每找到一个删除一个。
这是贪心的区间问题,每次找比当前晚且离当前最近的点(前提是没有重叠部分)。
注意:问题规模比较大,如果用枚举比较来查找的话可能会超时,可以用set,其查找的时间复杂度相当可观。但是一开始忽略了set不能有相同的元素这点,想要有相同元素可以用multiset。
还可以锻炼对set的应用
#include<iostream>
using namespace std;
#include<set>
#include<algorithm>
#define maxn 50005
struct point{
int x,y,id;
bool operator <(point a)const
{
return x<a.x;//重载小于号
}
};
multiset<point> t;
point p;
int num[maxn];
int main()
{
int n,m=0;
while(scanf("%d",&n)!=EOF)
{
point temp;
memset(num,-1,sizeof(num));
int a;
for(a=0;a<n;a++)
{
scanf("%d%d",&p.x,&p.y);
p.id=a;
t.insert(p);
}
multiset<point>::iterator i;
a=1;
while(!t.empty())
{
temp.x=t.begin()->y;//以最早点的结束时间为新的扩充起点
i=t.upper_bound(temp);//找开始时间比temp.x晚的点
while(i!=t.end())
{
temp.x=i->y;
num[i->id]=a;//记录位置
t.erase(i);//删除
i=t.upper_bound(temp);
}
num[t.begin()->id]=a++;
t.erase(t.begin());
}
printf("%d\n",a-1);
for(a=0;a<n;a++)
printf("%d\n",num[a]);
}
return 0;
}