/*Radar Installation
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 10128 Accepted: 1990
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
Source
Beijing 2002*/
#include "iostream"
#include "vector"
#include "math.h"
using namespace std;
class dot
{
public:
double x;
double y;
double l;
double r;
};
void solution(vector<dot> k,double d,int num)
{
int result = 1;
dot tmp;
if(d < 0)
{
result = -1;
cout<<"Case "<<num<<": "<<result<<endl;
return;
}
for(vector<dot>::iterator iter = k.begin();iter != k.end();iter++)
{
if((*iter).y > d)
{
result = -1;
cout<<"Case "<<num<<": "<<result<<endl;
return;
}
else
{
double s = sqrt(d * d - (*iter).y * (*iter).y);
(*iter).l = (*iter).x - s;
(*iter).r = (*iter).x + s;
}
}
for(vector<dot>::iterator iter = k.begin();iter != k.end();iter++)
{
for(vector<dot>::iterator iters = iter + 1;iters != k.end();iters++)
{
if((*iter).l > (*iters).l)
{
tmp = (*iter);
(*iter) = (*iters);
(*iters) = tmp;
}
else if((*iter).l == (*iters).l)
{
if((*iter).r > (*iters).r)
{
tmp = (*iter);
(*iter) = (*iters);
(*iters) = tmp;
}
}
}
}
double left = (*(k.begin())).l,right = (*(k.begin())).r;
for(vector<dot>::const_iterator iter = k.begin() + 1;iter != k.end();iter++)
{
if((*iter).l > right)
{
result++;
right = (*iter).r;
}
else
{
if((*iter).r < right)
{
right = (*iter).r;
}
}
}
cout<<"Case "<<num<<": "<<result<<endl;
return;
}
int main(void)
{
int n;
double d;
int num = 1;
while(cin>>n>>d)
{
if(n == 0 || d == 0)
{
break;
}
else
{
vector<dot> k;
dot m;
for(int i = 0;i < n;i++)
{
cin>>m.x>>m.y;
k.push_back(m);
}
solution(k,d,num++);
}
}
return 0;
}
贪心。。首先来看一种通常的情况。。以岛为圆心距离为半径画圆,圆与X轴相交于2个点,这2个点一左一右就产生了一个区间,实际上仔细思考就能明白X轴上处于这个区间内的点就是以这些点任一个为圆心距离d为半径画圆能够把当前这个岛包括进来的雷达的集合。。。那么一个岛的区间和另一个岛的区间若有重合区域。。那么就有雷达能够同时覆盖这2个岛。。如果没有重复区间。。那么就需要2个雷达了。。以此类推。。
以上就是这个题目的中心思想。。。具体做时先判断以岛为圆心d为半径画圆能不能与X轴相交。。如果出现不能相交的立即可以得出结论Case 1: -1(注意本题要判断d为负的情况,d为负时也是直接返回结果-1,不做这个判断这题AC不了)。。。。。然后根据左区间的大小把岛从小到大排序(左区间相同的右区间从小到大)。。这样就可以从左往右来做区间的合并了(当然从右到左也可以)。。。具体区间合并时看我上面的代码。。这题第2个难点就是如何分清楚区间的情况。。最好用纸画一画。。
1124



被折叠的 条评论
为什么被折叠?



