首页 > 代码库 > Poj 1328(雷达安装)几何+贪心

Poj 1328(雷达安装)几何+贪心

【题目描述】:

给定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 }