标签:
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 using namespace std; 6 struct ps 7 { 8 double left;//**左交点**// 9 double right;//**右交点**// 10 }w[10001]; 11 bool comp(ps a,ps b)//**还是按照左交点的大小进行排序**// 12 { 13 if(a.left<b.left) return true; 14 return false; 15 } 16 int main() 17 { 18 int ncases,n,i,width,high,x,r,count,flag; 19 double len,sum,max; 20 scanf("%d",&ncases); 21 while(ncases--) 22 { 23 flag=1;sum=0;count=0; 24 scanf("%d %d %d",&n,&width,&high); 25 for(i=0;i<=n-1;i++) 26 { 27 scanf("%d %d",&x,&r); 28 len=(double)r*r-(double)high/2*high/2; 29 if(len>=0) {len=sqrt(len);}//**以前把这布直接并入到sqrt(len),结果忘了len可以小于0,一直WA**// 30 if(len<0) {len=0;}//**覆盖不到,这个长度就可以忽略掉**// 31 w[i].left=x-len; 32 w[i].right=x+len; 33 } 34 sort(w,w+n,comp); 35 while(sum<width)//**关键思想**// 36 { 37 max=0;//**代表比前一个装置能够辐射的范围往右延长的最大值**// 38 for(i=0;i<=n-1&&w[i].left<=sum;i++)//**w[i].left<=sum保证两个碰水装置可以相交,也就是说两点直接的能够完全覆盖**// 39 { 40 if((w[i].right-sum)>max)//**找出既能保证完全覆盖又能保证这点能够达到的右交点最大,即需要的喷水装置最少**// 41 { 42 max=w[i].right-sum;//**找出最大值**// 43 } 44 } 45 if(max==0)//**说明w[i].left>sum,表示其中一个点的右交点跟另外一个点的左交点没有连接上,即不能完全覆盖**// 46 { 47 flag=0; 48 break; 49 } 50 else 51 { 52 sum=sum+max;//**更新能够覆盖的宽度**// 53 count++; 54 } 55 } 56 if(flag==1) 57 { 58 printf("%d\n",count); 59 } 60 else 61 { 62 printf("0\n"); 63 } 64 } 65 return 0; 66 } 67
转自http://blog.csdn.net/a_eagle/article/details/7269591
解题难点与思路:
1.不知道跟贪心有什么关系,于是联系到了radar(nyoj287)那道题目,发现两题有相似点,于是很快就会想到区间覆盖的题目,但是这个覆盖有点儿不同
2.知道了是区间覆盖后,但是不知道怎么满足把所有的地方都覆盖(就是选最好的区间段使得区间与区间之间没有间隙,一直到线段的最末端)。
3.贪心策略是将左端点从小到大排序,选择右端点,使得右端点尽量覆盖的最远
标签:
原文地址:http://www.cnblogs.com/WDKER/p/5362899.html