Description
Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point locating in the sea side. And any radar installation, locating on the coasting, can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance between them is at most d.
We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above x-axis, and the land side below. Given the position of each island in the sea, and given the distance of the coverage of the radar installation, your task is to write a program to find the minimal number of radar installations to cover all the islands. Note that the position of an island is represented by its x-y coordinates.
Figure A Sample Input of Radar Installations
Input
The input consists of several test cases. The first line of each case contains two integers n (1<=n<=1000) and d, where n is the number of islands in the sea and d is the distance of coverage of the radar installation. This is followed by n lines each containing two integers representing the coordinate of the position of each island. Then a blank line follows to separate the cases.
The input is terminated by a line containing pair of zeros
Output
For each test case output one line consisting of the test case number followed by the minimal number of radar installations needed. “-1” installation means no solution for that case.
Sample Input
3 2
1 2
-3 1
2 1
1 2
0 2
0 0
Sample Output
Case 1: 2
Case 2: 1
思路
雷达的搜索距离有范围d,那么可以收到某一个岛的全部雷达都在以到为圆心以d为半径的圆内。雷达都在都x轴上,那么雷达的范围就可以确定了,在圆与x轴的两个交点之间。也就是说,只有雷达在这个区间才可以搜索到该岛。将每一个岛存储为一个区间,问题就转换为了,求最少数的点,使所有区间内均有点。区间在读入数据时,用勾股定理即可求出。将所有区间按照左端点从小到大排序
如图,假设4条线段为4个区间,第二条线段的左端点小于第一条线段的右端点,那么将雷达放在第二条线段的左端点,可以覆盖第一个岛和第二个岛。第三条线段的左端点小于第二条线段的右端点,雷达放在第三条线段的左端点也可以。第四条线段的左端点大于第三条线段的右端点,放在第四条线段的左端点,不可以覆盖第三个岛,不行,所以雷达只能放在第三区间左端点。至于为什么都要放在左端点,因为如果放在左端点右面的,左端点前面可以到达的位置,左端点右面的点不都可以到达。当然放在右面的点可以在右面到达更大的范围,可能覆盖到后面的区间,但我们只考虑判断的区间前面的区间,后面的区间后面判断。也可以用右端点,那么排序时就要按照右端点来排序。
按照上面的方式遍历每一个区间,如果安置了一个雷达,更新雷达的位置,判断当前的区间和上一个雷达之间的区间是否覆盖。
最后答案需要加1,因为每次判断都是安装到前面的某个区间,这个区间的右端点大于正在判断的区间的左端点,那么将雷达安装在这个前面的某个区间的左端点,肯定没有在正在判断这个区间的范围内。所有最后另需一个雷达来覆盖最后一个岛。
注意,判断不成立的情况。读入数据时判断即可,如果岛的纵坐标的绝对值大于雷达的距离,则不成立。但此时不能退出循环,需要将所有的数据读完。还需注意,题中说点是整数,但数据不全是,用double存储。
代码
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
struct node
{
double l,r; //区间
}w[1005];
bool cmp(const node a,const node b)
{
return a.l<b.l; //排序从小到大
}
int main()
{
int cnt=0,n;
int d;
while(1)
{
cnt++;
cin>>n>>d;
if(n==0)
return 0;
bool flag=0;
for(int i=1;i<=n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(flag)
continue;
if(fabs(double(b))>d) //判断是否有可能
{
flag=1; //标记
continue; //继续读入数据
}
double tmp=(d*d-b*b); //勾股定理
w[i].l=a-sqrt(tmp); //区间
w[i].r=a+(tmp);
}
if(flag)
{
cout<<"Case "<<cnt<<": "<<"-1"<<endl;
continue;
}
sort(w+1,w+n+1,cmp); //排序
int pos=0,ans=0; //初始 雷达的位置为0,数量为0
for(int i=1;i<=n;i++)
{
for(int j=pos+1;j<i;j++) //上一个雷达的位置加1
{
if(w[i].l>w[j].r) //左端点>大于某个区间的右端点
{
ans++; //雷达需要放在上一个区间的左端点
pos=i-1;
break;
}
}
} //最后答案需要加1
cout<<"Case "<<cnt<<": "<<ans+1<<endl;
}
}