题目:有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。
思路:将坐标转换成区间,利用区间计算出覆盖范围。
import java.util.Scanner;
public class PengQuan2 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
while ((t--)> 0){
//表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。
int n = in.nextInt();
int w = in.nextInt();
int h = in.nextInt();
int[][] rx= new int[n][2]; //存储喷泉装置的横坐标和半径
double[][] rxo= new double[n][2]; //喷泉装置覆盖的范围
for (int i = 0; i < n; ++i){
double length = 0.0;
rx[i][0] = in.nextInt(); //横坐标
rx[i][1] = in.nextInt(); //半径
if (rx[i][1] <= h/2) {//当小于h/2 是不可以完整覆盖矩形,将覆盖的范围设置为0
length = 0.0;
rxo[i][0] = rxo[i][1] = 0.0;
}else{
length = Math.sqrt(rx[i][1]*rx[i][1] - (h/2.0)*(h/2.0));//计算出装置最大的覆盖范围
if ((rx[i][0] - length) <= 0)//当横坐标小于该长度时,左边的范围还是从0开始
{
rxo[i][0] = 0.0;
}else{
rxo[i][0] = rx[i][0] - length;//否则就是从它们之差算起
}
if ((rx[i][0] + length) >= w){//当横坐标加上长度大于宽度时,就实现完全覆盖,将另一边的范围设置为w
rxo[i][1] = w;
}else{
rxo[i][1] = rx[i][0] + length;//否则就是它们之和
}
}
}
//对范围的下限进行排序
for (int i = 0; i < n-1; ++i){
for (int j = n-i-1; j > 0; --j){
if (rxo[j][0] < rxo[j-1][0]){
double temp;
temp = rxo[j][0];
rxo[j][0] = rxo[j-1][0];
rxo[j-1][0] = temp;
temp = rxo[j][1];
rxo[j][1] = rxo[j-1][1];
rxo[j-1][1] = temp;
}
}
}
//找出最少装置
int count = 0; //所使用的最少装置数
int i,j;
double scale = 0.0;
int flag = 0;
int index = 0;
double mLength = 0.0;
for (j = 0; j < n; ++j){
mLength = 0.0;
flag = 0;
for (i = 0; i < n; ++i){
if ((rxo[i][0] <= scale) && (rxo[i][1] >= scale)){
if (rxo[i][1] - scale > mLength){
mLength = rxo[i][1] - scale;
index = i;
flag = 1;
}
}
}
if (flag == 1){
scale = rxo[index][1];
count++;
}
if (scale >= w){
System.out.println(count);
break;
}
}
if (j == n){
System.out.println(0);
}
}
}
}