雷达安装
题目描述:
假定海岸线是一条无限延伸的直线,陆地在海岸线的一边,大海在另一侧。海中有许多岛屿,每一个小岛我们可以认为是一个点。现在要在海岸线上安装雷达,雷达的覆盖范围是d,也就是说大海中一个小岛能被安装的雷达覆盖,那么它们之间的距离最大为d。
我们使用平面直角坐标系,定义海岸线是x轴,大海在x轴上方,陆地在下方。给你海中每一个岛屿的坐标位置(x,y)和要安装的雷达所覆盖的范围d,你的任务是写一个程序计算出至少安装多少个雷达能将所有的岛屿覆盖。
输入描述:
第一行两个整数n(1≤n≤100000)和d,分别表示海中岛屿的数目和雷达覆盖的范围半径d。
接下来n行,每行两个整数,表示每个岛屿的坐标位置(x,y)。
输出描述:
一行一个整数,即能将所有岛屿全部覆盖至少安装的雷达个数,如果无解则输出“-1”。
样例输入
3 2 1 2 -3 1 2 1 1 2 0 2 0 0
样例输出
Case 1: 2 Case 2: 1
数据范围及提示:
(1≤n≤100000)
注意会输出-1
思路:
贪心思想
贪心算法:
1 ) 将所有区间按照起点从小到大排序,并编号0 - (n-1)
2 ) 依次考察每个区间的起点,看要不要在那里放雷达。开始,所有区间都没被覆盖,所以目前编号最小的未被覆盖的区间的编号 firstNoConverd =0
3 ) 考察一个区间 i 的起点 xi的时候,要看从 firstNoCovered 到区间i-1 中是否存在某个区间 c ,没有被 xi 覆盖。如果没有,则先不急于在xi放雷达,接着往下看。如果有,那么 c 的终点肯定在xi的左边,因此不可能用同一个雷达覆盖 c 和i。即能覆盖c的点,已经不可能覆盖i和i后面的区间了。此时,为了覆盖c,必须放一个雷达了,放在区间 i-1 的起点即可覆盖所有从firstNoCovered到 i-1的区间。因为当初考察 i-1的起点 z时候,并没有发现 z 漏覆盖了从 firstNoCovered 到 i-2 之间的任何一个区间
4) 放完雷达后,将 firstNoCovered改为i,再做下去。
这题为贪心题,看到题目,不难想到,如果在岛屿正下方的雷达监测不到岛屿,那该岛屿必定是监测的不到的,在读完该组数据后输出-1即可。因此,对于每一个岛屿,我们以h为半径画圆,如果与x轴没有交点,则该岛无法被监测到,否则,将其与x轴的两个交点存入数组a,b。在所有交点存入数组后,以每个岛的左边的交点为关键字排序。设置一个变量r,为雷达的位置,将排序后的b[1]赋值给r,从第二个岛屿开始找,如果第二个岛屿的靠左的交点在r的监测范围之外,则将雷达数+1,将第二个岛屿靠右的交点赋值给r,如果第二个岛屿的靠右的交点在r的监测范围之内,直接将b[2]赋值给r;依此类推。
#include <iostream> #include <cmath>#include <algorithm> #define NUM 1001 using namespace std; //n代表小岛数,N代表小岛在island_x轴上的所有区间个数 struct QU_jian { double l;//左边点 double r;//右边点 bool operator<(const QU_jian& t)const{ return this->l<t.l; } }N[NUM]; int main() { int n,d; double island_x,island_y;//每一个小岛的坐标 int k = 1;//案例数 while(cin>>n>>d&&n&&d){ int radar_min_num = 1; for (int i = 0;i<n;i++){ cin>>island_x>>island_y; if(island_y<=d && d>0 && island_y>=0){ N[i].r=island_x+(double)sqrt(d*d - island_y*island_y); N[i].l=island_x-(double)sqrt(d*d - island_y*island_y); } else{ radar_min_num = -1;//读错半径和island_y的坐标继续读 } } //用几何关系找到每一个小岛需要固定的半径的雷达在island_x轴上的最大和最小值范围 sort(N, N+n); //对左端的数据从小到大排序 double temp = N[0].r; for( int i = 1;(i<n && radar_min_num != -1);i++){ if(temp<N[i].l){ temp = N[i].r; radar_min_num++; } else{ if(N[i].r<temp) temp = N[i].r; } } //利用贪心算法找到最优 cout <<"Case "<<k++<<": "<<radar_min_num<<endl;//打印结果 } return 0; }