【原创】【区间上的贪心 第一篇】Poj 1328 Radar Installation

区间上的各种贪心

不多说,看题。

选点覆盖区间

Radar Installation POJ 1328

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

题意

平面直角坐标系上有n个点,求在x轴上找尽量少的点,以这些点为圆心画一个半径为d的圆,使得给定的点都在画出来的圆里。如果不能输出-1。

分析

我的思路是由最后一句话“如果不能输出-1”启发的。
怎么会不能呢?因为x轴上所有点到某点的距离都超过了d。
也就是说,以这个点画一个半径为d的圆,它与x轴无交点。
如图:
这里写图片描述
我们知道圆心和半径,可以求出圆的方程:(x-a)²+(y-b)²=d²,
它与x轴即y=0无交点,则说明联立圆和y=0,无解。
这里写图片描述
回到图形,
这里写图片描述
如果想要在x轴上选点画圆覆盖(a,b),那么这个点的横坐标就一定在[a-d²+b²,a+d²-b²]区间内。

因此,这道题就变成了在数轴上选最少的点,覆盖给定线段。
这就类似于整数区间了。

假设数轴上有很多段区间,我们把它们从数轴上分离出来。
这里写图片描述
把一维拓展到二维,就很直观了,取点的过程可以理解为画一条铅垂线来割这些线段。
让我们先来割第一条线段。随便画几条线。
这里写图片描述
我们可以直观地感受到,从靠第一条线段的地方割,越容易割到其他的线,也就是说有更多的线段不用多浪费线去割。
为什么呢?
图上可以看到,其他的线段都比第一条线段“靠右”,因此,选择割点的时候,如果想要尽量多覆盖,割点也要尽量“靠右”。
怎么用程序实现靠左和靠右呢?我们可以将线段以右端点排序,就可以达到如上效果。

代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;

void Read(int &p)
{
    p=0;
    int f=1;
    char c=getchar();
    while(c<'0'||c>'9') 
        f=(c=='-')?-1:1,c=getchar();
    while(c>='0'&&c<='9')
        p=p*10+c-'0',c=getchar();
    p*=f;
}

struct point
{
    double l,r;
    bool operator < (const point &x) const 
    {
        if(r!=x.r) return r<x.r;
        return l<x.l;
    }
}p[1234];

int n,x,y,d,sp;
double delta;

int main()
{
    while(1)
    {
        Read(n); Read(d);
        if(!n&&!d) break;
        bool f=1;
        for(int i=1;i<=n;i++)
        {
            Read(x); Read(y);
            delta=1.0*d*d-1.0*y*y;
            if(d>=y)
                p[i].l=x-sqrt(delta),
                p[i].r=x+sqrt(delta);
            else f=0;
        }

        if(!f) 
        {
            printf("Case %d: -1\n",++sp);
            continue;
        }

        sort(p+1,p+1+n);
        double now=p[1].r;
        int ans=1;
        for(int i=2;i<=n;i++)
            if(p[i].l>now)
                ans++,now=p[i].r;
        printf("Case %d: %d\n",++sp,ans);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值