Link: http://poj.org/problem?id=1328
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
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.
想法:
正常情况,岛屿可以被雷达监视到,那么以这个岛为圆心画一个圆必然交海岸线于两点(有可能共点),对每个岛将这两个点x坐标按左右设为l和r,
将岛屿按照r升序排序,设立对比值key为最新建立的雷达覆盖的岛屿中的最小的r值,那么按编号由小到大扫描,需要新增雷达的条件是:
下一个岛屿的l比key要大
这时需要做的处理是,更新key为这个岛屿的r值(相当于新建了一个雷达站在r处),并将雷达数目加上1
否则continue
这个贪心算法的正确性在于,它相当于在每次新开雷达站时,将这个雷达站设在本次建立后第一个扫描的岛的r值处并设其为对比值key,由于按r升序排序的特性,
在扫描到第一个l值比key大的岛屿之前,所有岛都能被包括在雷达内,
这样做得到的num和“每次能将所有l值小于key的岛都包括在内”是一样的,因为对由于在扫描到l值比key大的岛屿后没有计入的这部分岛屿,它们的l值肯定比当前的key小,
而且它们的r值也肯定比当前的key大,它们对应一个更大的区间,肯定能被后面建立的雷达站覆盖进去,所以对后面雷达站的建立不会起影响
也就是说,每次新建雷达站都尽可能多地包含了岛屿
特殊情况,
1. d<0或y<0 数据无效,肯定不行
2. d==0且存在y!=0 覆盖不到,肯定不行
3. d==0且所有y==0 那么每个岛都要一个雷达站,直接输出n(话说真有这情况么..)
4. y>d 覆盖不到,肯定不行
Sample Input
3 2 1 2 -3 1 2 1 1 2 0 2 0 0
Sample Output
Case 1: 2 Case 2: 1
想法:
正常情况,岛屿可以被雷达监视到,那么以这个岛为圆心画一个圆必然交海岸线于两点(有可能共点),对每个岛将这两个点x坐标按左右设为l和r,
将岛屿按照r升序排序,设立对比值key为最新建立的雷达覆盖的岛屿中的最小的r值,那么按编号由小到大扫描,需要新增雷达的条件是:
下一个岛屿的l比key要大
这时需要做的处理是,更新key为这个岛屿的r值(相当于新建了一个雷达站在r处),并将雷达数目加上1
否则continue
这个贪心算法的正确性在于,它相当于在每次新开雷达站时,将这个雷达站设在本次建立后第一个扫描的岛的r值处并设其为对比值key,由于按r升序排序的特性,
在扫描到第一个l值比key大的岛屿之前,所有岛都能被包括在雷达内,
这样做得到的num和“每次能将所有l值小于key的岛都包括在内”是一样的,因为对由于在扫描到l值比key大的岛屿后没有计入的这部分岛屿,它们的l值肯定比当前的key小,
而且它们的r值也肯定比当前的key大,它们对应一个更大的区间,肯定能被后面建立的雷达站覆盖进去,所以对后面雷达站的建立不会起影响
也就是说,每次新建雷达站都尽可能多地包含了岛屿
特殊情况,
1. d<0或y<0 数据无效,肯定不行
2. d==0且存在y!=0 覆盖不到,肯定不行
3. d==0且所有y==0 那么每个岛都要一个雷达站,直接输出n(话说真有这情况么..)
4. y>d 覆盖不到,肯定不行
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct island
{
int x, y;
double l, r;
};
int n;
int d;
island a[1000];
bool cmp(island a, island b)
{
if (a.r == b.r)
return a.l < b.l; //加上这句之后莫名地快了16ms.. 不知道为什么
return a.r < b.r;
}
int main()
{
int c = 1;
while (~scanf("%d %d", &n, &d) && !(n == 0 && d == 0))
{
int num = 1,flag=0;
for (int i = 0; i < n; i++)
{
scanf("%d %d", &(a[i].x), &(a[i].y));
if (a[i].y < 0)
flag = 1;
else if (a[i].y>d)
flag = 1;
}
if (flag)
{
printf("Case %d: -1\n", c++);
continue;
}
if(d<0)
{
printf("Case %d: -1\n", c++);
continue;
}
if (d == 0)
{
for (int i = 0; i < n; i++)
{
if (a[i].y != 0)
{
printf("Case %d: -1\n", c++);
break;
}
if (i == n - 1)
printf("Case %d: %d",c++,n);
}
continue;
}
for (int i = 0; i < n; i++)
{
a[i].l = double(a[i].x) - sqrt(double(d*d - a[i].y*a[i].y));
a[i].r = double(a[i].x) + sqrt(double(d*d - a[i].y*a[i].y));
}
sort(a, a + n, cmp);
double key=a[0].r;
for (int i = 1; i < n; i++)
{
if (a[i].r == key)
continue;
else
{
if (a[i].l > key)
{
num++;
key = a[i].r;
}
}
}
printf("Case %d: %d\n",c++,num);
}
return 0;
}