Uva10382 Watering Grass

题目链接: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");
				
			}
		}
	}

}


你可能感兴趣的:(Uva10382 Watering Grass)