POJ

来源:互联网 发布:网络电视机顶盒功能 编辑:程序博客网 时间:2024/05/17 07:04

问题描述
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轴上安放雷达,每一个雷达覆盖的范围是一个以d为半径的圆。在海上(y>0)的区域内有n个岛屿,要求安放最少的雷达覆盖所有的岛屿。

首先我自己分析这个题目的时候想到了POJ-3069这个题目,题目大意就是在一条直线上(一维空间),有多个点,然后给它们加上标记,对每个点,其距离为R以内的区域内必须有标记的点,求最少的标记点数目。想了半天啊,发现根本不是这个思路,虽然也相当于在x轴这条线上找标记点,但是它覆盖的区域是二维空间里的点,这样无法按照一维的先排序再贪心。

所以换思路,它要求在x轴上找点作为雷达,这个点肯定在一个区间内都可以覆盖到某个岛屿,那么就利用一下简单的平面几何知识,以岛屿为圆心,d为半径画圆,交于x轴两点,那么这两点就是雷达可覆盖到此岛屿的区间范围,那么把所有的岛屿都如此操作,并将区间存放,这样如果有多个岛屿的区间有相交的部分,那么雷达就可以放在相交的区间内,这样此雷达就可以覆盖到多个岛屿了,也就转换为最大不相交覆盖问题。

注意,如果d < 0 , 或者一个岛屿的y<0(题目要求岛屿只能在海域) ,或者某个岛屿的y > d(这样x轴上不可能有雷达能覆盖到此岛屿),这些情况都是无法解决的,输出-1。PS:在这上面wa了好多次。

#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int maxn = 1000+10;int n, d;struct Island{    double x,y;}island[maxn];struct Interval{    double start, end;}a[maxn];int cmp(const Interval &a, const Interval &b){    if(a.end < b.end) return 1;    else if(a.end == b.end && a.start < b.start) return 1;    else return 0;}/*找圆与x轴交点的左端点*/double left_x(double x, double y){    double x_len = sqrt(d*d - y*y);    return x-x_len;}/*找圆与x轴交点的右端点*/double right_x(double x, double y){    double x_len = sqrt(d*d - y*y);    return x+x_len;}/*最大不相交覆盖的解决*/void solve(){    sort(a, a+n, cmp);    double e = a[0].start - 1;    int count = 0;    for(int i=0; i<n; i++)    {        if(a[i].start > e)          {            count++;            e = a[i].end;        }    }    printf("%d\n",count);    return;}int main(){    int k = 0;    while(scanf("%d%d",&n, &d)!=EOF)    {        int ok = 1;        if(n == 0 && d == 0) break;        for(int i=0; i<n; i++)        {            scanf("%lf%lf",&island[i].x, &island[i].y);            if(island[i].y > d || island[i].y < 0) ok = 0;//注意细节            a[i].start = left_x(island[i].x, island[i].y);            a[i].end = right_x(island[i].x, island[i].y);        }           if(!ok)        printf("Case %d: -1\n",++k);        else{            printf("Case %d: ",++k);            solve();        }    }       return 0;}
0 0