poj_1328_Radar Installation(区间贪心)

題型:貪心

題意

       有n個點在海里,現在需要用雷達將這些店覆蓋,雷達的輻射範圍是半徑為d的圓,設海岸綫為x軸,雷達要建在x軸上,問最少要多少個雷達能將這些點全部覆蓋。

分析

        既然雷達具有輻射半徑,那麽對於點(x,y),如果y>d,那麽就不可能被覆蓋到,則輸出-1;如果y<=d,那麽雷達安裝的範圍必須在[x-sqrt(d^2-y^2),x+sqrt(d^2-y^2)]區間内。

        首先求出每個點所要求的區間,然後按集合右邊界大小進行排序,然後從左邊的集合的右邊界開始找,若該邊界所處集合所屬的點沒有被覆蓋,那麽在這個集合的右邊界檢建一個雷達,然後將集合左邊界處於該雷達左邊的集合刪除,最後貪心下去即可得到答案。

代碼

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define eps 1e-10
#define maxn 1234
using namespace std;
struct point {
    double x,y;
} p[maxn];

struct Node{
    double l,r;
    bool flag;
}h[maxn];

int n;
double d;

bool cmp(Node a,Node b) {
    if(fabs(a.r - b.r) < eps)
        return a.l < b.l;
    return a.r < b.r;
}

double funl(double x,double y) {
    return x - sqrt(1.0*d*d-y*y);
}
double funr(double x,double y) {
    return x + sqrt(1.0*d*d-y*y);
}

int main() {
    int time = 0;
    while(1) {
        time++;
        scanf("%d%lf",&n,&d);
        if(n==0 && d==0) break;
        for(int i=0; i<n; i++) {
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        bool vis = true;
        for(int i=0; i<n; i++) {
            if(p[i].y > d) {
                vis = false;
                break;
            }
            h[i].l=funl(p[i].x,p[i].y);
            h[i].r=funr(p[i].x,p[i].y);
            h[i].flag=true;
        }
        if(!vis){
            printf("Case %d: -1\n",time);
            continue;
        }

        int ans=0;
        sort(h,h+n,cmp);

        for(int i=0;i<n;i++){
            if(h[i].flag){
                ans++;
                for(int j=0;j<n;j++){
                    if(h[j].l < h[i].r+eps && h[j].flag == true){
                        h[j].flag=false;
                    }
                }
            }
        }
        printf("Case %d: %d\n",time,ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值