描述
有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。
输入##
第一行输入一个正整数N表示共有n次测试数据。
每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。
随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
输出
每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。
如果不存在一种能够把整个草坪湿润的方案,请输出0。
样例输入
2
2 8 6
1 1
4 5
2 10 6
4 5
6 5
样例输出
1
2
解题思路
题目意思就是在[0,w]区间上,尽可能少的用给出的固定区间填满。给出的喷头坐标与半径需要转换以存储方便使用
贪心算法
遍历数组寻找一个左边在起点b左边并且右边界最大的区间max,找到以后就将这个右边界作为新的起点b,循环,直到max>=w
AC代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class Node implements Comparable<Node> {
private double left;
private double right;
public double getLeft() {
return left;
}
public void setLeft(double left) {
this.left = left;
}
public double getRight() {
return right;
}
public void setRight(double right) {
this.right = right;
}
public int compareTo(Node o) {
return (int)(o.left-this.left);
}
}
public class acm12 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
while(m-->0){
int flag = 0;
int n = sc.nextInt();
double w = sc.nextDouble();
double h = sc.nextDouble();
ArrayList<Node> list = new ArrayList<Node>();
for(int i = 0; i<n;i++) {
double x = sc.nextDouble();
double r = sc.nextDouble();
double length = r*r-(h/2.0)*(h/2.0);
if(length>0) {
length = Math.sqrt(length);
Node obj = new Node();
obj.setLeft(x-length);
obj.setRight(x+length);
list.add(obj);
}
}
Collections.sort(list);
double sum = 0;
int count = 0;
while(sum<w) {
double max = 0;
for (Node obj : list) {
if((obj.getLeft()<=sum)&&(obj.getRight()-sum>max)) {
max = obj.getRight()-sum;
}
}
if(max==0.0) {
flag = 1;
break;
}
else {
sum = sum +max;
count ++;
}
}
if(flag==1) {
System.out.println(0);
}
else {
System.out.println(count);
}
}
sc.close();
}
}