POJ 1328 Radar Installation - 贪心算法

来源:互联网 发布:python 创建数据库 编辑:程序博客网 时间:2024/05/29 08:52

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


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 21 2-3 12 11 20 20 0

Sample Output

Case 1: 2Case 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;}



0 0
原创粉丝点击