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;
}