《黑书》uva10148(区间选点问题)贪心
题意:有n段区间,每段区间至少要有k个广告牌,要求你在这些区间放置广告牌,但是广告牌的数量要是最少的,而且将其位置输出来。
思路:经典贪心,区间选点问题。《算法入门经典》P154。
假设每个区间是【ai, bi】, 那么先按照每个区间的bi从小到大排序。
下图是排好序的四个区间。为了使得广告位数量最少,那么就要让这些广告位尽量的处在越多人重复经过的地方越好。
观察下图可以看出,为了让重叠部分越多,那么每个区间选点时,就要让这些点尽可能的往改区间的右边靠。
在对每个区间选点时,先查看该区间之前已经被选好几个点了,如果不够的话再补上。

代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct ss
{
int x,y;
}s[1005];
int vist[20005];
int cmp(const ss a,const ss b)
{
if(a.y<b.y)
return 1;
else
return 0;
}
int main()
{
int text;
scanf("%d",&text);
while(text--)
{
int n,k;
scanf("%d%d",&k,&n);
int maxx=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&s[i].x,&s[i].y);
if(s[i].x>s[i].y)
{
int tmp=s[i].x;
s[i].x=s[i].y;
s[i].y=tmp;
}
s[i].x+=10000;
s[i].y+=10000;
if(maxx<s[i].y)
maxx=s[i].y;
}
memset(vist,0,sizeof(vist));
sort(s,s+n,cmp);
int sum=0;
for(int i=0;i<n;i++)
{
int flag=0;
for(int j=s[i].x;j<=s[i].y;j++)
if(vist[j])
flag++;
if(flag>=k)
continue;
else
{
for(int j=s[i].y;j>=s[i].x&&flag<k;j--)
if(!vist[j])
{
vist[j]=1;
flag++;
sum++;
}
}
}
printf("%d\n",sum);
for(int i=0;i<=maxx;i++)
if(vist[i])
printf("%d\n",i-10000);
if(text)
printf("\n");
}
return 0;
}
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。

浙公网安备 33010602011771号