UVA 10382 - Watering Grass(贪心)

题目链接 https://cn.vjudge.net/problem/UVA-10382

【题意】
有一块草坪,长为L,宽为W.在其中心线的不同位置装有n个点状的喷水装置,每个喷水装置i可以将它以i为中心,半径为ri的圆形区域润湿,请选择尽量少的喷水装置把整个草坪全部润湿。

【输入格式】
多组输入。每种数据第一行为n,L,W(1<=n<=10000)以下n行每行两个整数pi,ri,即每个喷水装置的位置和半径。

【输出格式】
对每组数据,输出需要打开喷水装置数目的最小值。无解输出-1.

【思路】
首先要将每个装置覆盖的圆形转换为草坪上的矩形,如果半径r<=W/2那么直接舍弃,否则的话该装置可以完全覆盖掉[p-sqrt(r^2-W^2/4),p+sqrt(r^2-W^2/4)]的区间,进而转换成了区间覆盖问题,按照区间左端点从小到大排序,定义一个变量maxr为当前覆盖到的最右端点,每次取区间的左端点还没有越过maxr中的区间里找一个右端点最大的作为答案,不断重复这个过程。

#include<bits/stdc++.h>
using namespace std;

const int maxn=10050;

struct node{
    double le,ri;
    node(double l,double r):le(l),ri(r){}
    bool operator<(const node& e)const{
        return le<e.le;
    }
};

int n;
double L,W;
vector<node> v;

int main(){
    while(scanf("%d%lf%lf",&n,&L,&W)==3){
        v.clear();
        for(int i=0;i<n;++i){
            double p,r;
            scanf("%lf%lf",&p,&r);
            if(r<=W/2) continue;
            double x=sqrt(r*r-W*W/4.0);
            if(p+x>=0 || p-x<=L) v.push_back(node(p-x,p+x));
        }
        sort(v.begin(),v.end());
        int ans=0;
        bool ok=1;
        double maxr=0;
        int i=0;
        while(1){
            if(v[i].le>maxr) { ok=0;break; }
            double tmp=0;
            ++ans;
            for(;i<v.size() && v[i].le<=maxr;++i){
                tmp=max(tmp,v[i].ri);
            }
            maxr=max(maxr,tmp);
            if(i==v.size()||maxr>=L) break;
        }
        if(maxr<L) ok=0;
        if(!ok) puts("-1");
        else printf("%d\n",ans);
    }
    return 0;
}
posted @ 2018-07-29 15:12  不想吃WA的咸鱼  阅读(232)  评论(0编辑  收藏  举报