《黑书》uva10148(区间选点问题)贪心
题意:有n段区间,每段区间至少要有k个广告牌,要求你在这些区间放置广告牌,但是广告牌的数量要是最少的,而且将其位置输出来。
思路:经典贪心,区间选点问题。《算法入门经典》P154。
假设每个区间是【ai, bi】, 那么先按照每个区间的bi从小到大排序。
下图是排好序的四个区间。为了使得广告位数量最少,那么就要让这些广告位尽量的处在越多人重复经过的地方越好。
观察下图可以看出,为了让重叠部分越多,那么每个区间选点时,就要让这些点尽可能的往改区间的右边靠。
在对每个区间选点时,先查看该区间之前已经被选好几个点了,如果不够的话再补上。
![](http://my.csdn.net/uploads/201208/15/1345038093_5414.jpg)
代码:
#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; }
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。