Radar Installation
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 84620 | Accepted: 18898 |
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
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
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
/*******************************************
这么一个题居然做了俩小时,心疼自己的青春。。
一开始思路错了
错误思路:从左到右枚举点。如果点被包含在已有
的区域内,则不管。如果没有被包含,则需要增加
一个雷达。这个雷达在包含这个点的前提下尽可能
的靠右。因为有y的限制,所以这个贪心思路是不
对的(如果不用考虑y而但考虑x的话,这样是没
问题的。可这样就水的不像样子了)。
wa炸了就跑去看dicuss,测了几组数据才发现原来
思路错了。
然后不小心看到了大佬的思路(感觉这思路自己完
全能想到)。于是按照对的思路又开始写。
沿着正确思路写的时候,脑子里忽然冒出来很多奇
技淫巧,像什么求前缀和呀,栈啊之类的。想到一
出是一出,写完了测数据发现不对,又推了重写。
所以以后还是把思路想明白了再动手写,省得浪费
时间。
还有,如果是比赛的时候,效率差不多的情况下还
是选择更朴素的、更熟悉的方法比较靠谱。
就这么两个小时过去了。。。万幸今天晚上还能把
它写对。下面上具体方法。
*********************************************
首先以每个点为圆心,d为半径画圆,交x轴于两点
l, r。
如果交不上,那就说明出现了 y>d 或 d=0 的情况,
初次之外不合法的情况还有 y<0 和 d<0。对于不
合法的情况,直接输出-1就可以了。
每一对l,r形成了一个区间。每一个区间内都至少
要有一个雷达。
将各区间按 l 从小到大进行排序,然后逐个枚举。
如果后面一个区间的 l 小于等于当前区间的 r,说
明这两个区间有交集,只要在这个交集内安一个雷
达就能覆盖这两个岛了。
先别急这放雷达,万一能用一个雷达覆盖更多的岛
呢。所以,这时要做的时更新 e,e就是当前区间
的右端点,它的值为当前区间内所有 l,r 区域的
r的最小值。也就是e=min(e,r)。
如果后面一个区间的 l 大于当前区间的 r ,说明
这两个区间没有交集,那就在前一个区间的交集上
放一个雷达,然后 e=r。
这里需要注意的一点是,我们每次都是把相交的区
间都处理完了才给放雷达,也就是始终都是欠着一
个雷达的。所以输出结果时要加上1。
*******************************************/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef pair<double, double> P;
P land [1010];
P f (int x, int y, int d)
{
P ans;
ans.first = x - sqrt(1.0*d*d - 1.0*y*y);
ans.second = x + sqrt(1.0*d*d - 1.0*y*y);
return ans;
}
int main ()
{
int n, d, cas = 0;
while(1){
bool flag = 0;
scanf("%d %d", &n, &d);
if( n == 0 && d == 0 ) return 0;
for(int i= 0; i< n; i++){
int x, y;
scanf("%d %d", &x, &y);
if( d <= 0 || y < 0 || y > d ) flag = 1;
land[i] = f(x, y, d);
}
if( flag ){
printf("Case %d: -1\n", ++cas);
continue;
}
sort(land, land+n);
int cnt = 0;
double e = land[0].second;
for(int i= 1; i< n; i++){
if(land[i].first <= e) e = min(e, land[i].second);
else cnt ++, e = land[i].second;
}
printf("Case %d: %d\n", ++cas, cnt+1);
}
return 0;
}