【题目描述】:
给定n个小岛以及这些小岛的位置,并输入雷达的辐射面积,问最少需要多少个雷达站才能覆盖所有小岛?
【思路分析】:
本题首先想到的是运用贪心算法,但是算法想到了如何贪心?这道题我自己开始做之时只有一点思路,就是让每一个雷达覆盖较多的点,但是如何较多覆盖,这就是典型的数学问题了,自己没有思索出来,最后在网上看了题解才明白如何做。下面我们看看如何建图:
我们通过这个图首先运用了一个数学知识,就是以小岛为圆心,雷达辐射范围为圆心建立一个圆,该圆与x轴有一个交点,以该交点作为雷达站铺设点那么该雷达站一定可任意覆盖小岛。同时如果以各个小岛为圆心建立的圆如果不相交,那么肯定要多个雷达站,如果某一个小岛为圆心的圆与x轴的右交点比另外一个小岛为圆心的圆的右交点小,那么这两个小岛一定可以被同一个雷达覆盖。
当然我们在处理数据的时候,我们需要对数据进行排序。
【AC代码】:
1 #include<iostream> 2 #include<math.h> 3 #include<algorithm> 4 using namespace std; 5 #define max 1005 6 struct radar 7 { 8 double left; 9 double right; 10 double x; 11 double y; 12 }r[max]; 13 int cmp(radar a,radar b) 14 { 15 return a.left<b.left;//对小岛构成的圆与x轴的左交点进行从小到大的排序 16 } 17 int main() 18 { 19 int count=1,n,d; 20 while(cin>>n>>d&&(n||d)) 21 { 22 int flag=0,sum=1; 23 double x,y; 24 for(int i=0;i<n;i++) 25 { 26 cin>>x>>y; 27 if(y>d) flag=1; 28 r[i].x=x; 29 r[i].y=y; 30 } 31 32 for(int i=0;i<n;i++ ) 33 { 34 r[i].left=r[i].x*1.0-sqrt(d*d-r[i].y*r[i].y) ;//计算圆与x轴的左右交点 35 r[i].right=r[i].x*1.0+sqrt(d*d-r[i].y*r[i].y) ; 36 } 37 sort(r,r+n,cmp); 38 if(flag) {cout<<"Case "<<count++<<": -1"<<endl;continue;} 39 double temp=r[0].right; 40 for(int i=1;i<n;i++) 41 { 42 if(r[i].left>temp) 43 { 44 sum++;temp=r[i].right; //如果两个圆不相交,那么雷达数目加1. 45 } 46 else if(r[i].right<temp) 47 { 48 temp=r[i].right;//如果某一个圆的右交点比令一个圆的右交点小,那么更新圆。 49 } 50 } 51 cout<<"Case "<<count++<<": "<<sum<<endl; 52 } 53 return 0; 54 }