题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1323
题目大意:一个长l,宽w的条状草皮,上面分布多个喷水器,每个喷水器以距离草皮左边界的距离和喷水半径表示。求解最少需要个喷水器,可以将草皮全部覆盖。
解题关键:
(1)利用草皮宽度w和喷水器的半径r,算出每个喷水器在草皮上的覆盖范围(一个矩形){segs[i].left,segs.right[i]};
(2)转换为区间覆盖问题,贪心求解,将喷水器按照覆盖范围最左边的坐标segs[i].left,从小到大排序,第一个喷水器的left应《=0,其后的喷水器选择,应该在保证segs[i].left<=segs[i-1].right的情况下,segs[i].right尽可能的大。
import java.util.*;
class Segment {
public double left;
public double right;
Segment(double le,double ri){
this.left=le;
this.right=ri;
}
}
class Comp implements Comparator<Segment>{
@Override
public int compare(Segment o1, Segment o2) {
// TODO Auto-generated method stub
if(o1.left<o2.left)
return -1;
else if(o1.left>o2.left)
return 1;
return 0;
}
}
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int n;
double l,w,p,r;
Scanner in=new Scanner(System.in);
Segment[] segs=null;
while(in.hasNext())
{
n=in.nextInt();
l=in.nextDouble();
w=in.nextDouble();
segs=new Segment[n];
for(int i=0;i<n;i++){
p=in.nextDouble();
r=in.nextDouble();
double left=p-Math.sqrt(r*r-w*w/4);
double right=p+Math.sqrt(r*r-w*w/4);
segs[i]=new Segment(left,right);
}
Arrays.sort(segs,new Comp());
if(segs[0].left>0)
System.out.println("-1");
else
{
int ans=1;
boolean flag=false;
double pre=Double.MIN_VALUE;
for(int i=0;i<n&&segs[i].left<=0;i++)
pre=(pre<segs[i].right? segs[i].right:pre);
while(true)
{
if(pre>=l) {flag=true;break;}
double Max=Double.MIN_VALUE;
for(int i=0;i<n&&segs[i].left<=pre;i++)
Max=(segs[i].right>Max? segs[i].right:Max);
if(pre>=Max) {flag=false;break;}
else
{
ans++;
pre=Max;
}
}
if(flag==true)
System.out.println(ans);
else
System.out.println("-1");
}
}
}
}