喷泉装置2

题目:有一块草坪,横向长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);
            }
        } 
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值