动态规划之照明路灯

题目

一条长l的笔直的街道上有n个路灯,若这条街的起点为0,终点为l,第i个路灯坐标为ai ,每盏灯可以覆盖到的最远距离为d,为了照明需求,所有灯的灯光必须覆盖整条街,但是为了省电,要使这个d最小,请找到这个最小的d。
来源:牛客网

测试用例

输入:
每组数据第一行两个整数n和l(n大于0小于等于1000,l小于等于1000000000大于0)。第二行有n个整数(均大于等于0小于等于l),为每盏灯的坐标,多个路灯可以在同一点。
7 15
15 5 3 7 9 14 0

输出:
输出答案,保留两位小数。
2.50

思路

  • 约束:
    1. 灯光覆盖整条街。
    2. d能满足要求,且取最小值。
  • 路灯照射区域为圆形区域,d可以作为半径。
  • 为了使d尽可能小,在满足能够完全覆盖的情况下,需要尽量减少重合区域。
  • 我们需要优先满足大间隔的覆盖,之后处理小间隔。
  • 我们设计间隔变化的状态转移方程:
    1. L:左端第一个路灯到道路左端的距离。
    2. R: 右端第一个路灯到道路右端的距离。
    3. M: 两端路灯之间的最大距离/2(因为此处两边都有路灯)。
  • 此处处理 M M M遇到一些障碍,每次遍历找到最大 M M M明显是不智的。如果我们事先将路灯位置数组 n u m s nums nums排序,我们的 L L L不会频繁变化, M M M也只需要计算新增的间隔与上一步 M M M比较即可。

S o r t ( n u m s ) L = n u m s [ 0 ] − 0 R = l − n u m s [ i ] M = M A X ( n u m s [ i ] − n u m s [ i − 1 ] , M ) d = M A X ( L , R , M ) \begin{aligned} &Sort(nums)\\ L &= nums[0]-0\\ R &= l - nums[i]\\ M &= MAX(nums[i]-nums[i-1],M)\\ d &= MAX(L,R,M) \end{aligned} LRMdSort(nums)=nums[0]0=lnums[i]=MAX(nums[i]nums[i1],M)=MAX(L,R,M)

import java.util.*;
public class Main{
    
    public static void solve(int n,int l,int[]index){
        double L = 0,R = 0,M = 0,d = 0;
        Arrays.sort(index);
        L = index[0] - 0;
        R = l - index[n-1];
        double tmp = L>R?L:R;
        for(int i=1;i<n;i++){
            M = M>(index[i]-index[i-1])/2.0?M:(index[i]-index[i-1])/2.0;
        }
        d = M>tmp?M:tmp;
        
        System.out.println(String.format("%.2f",d));
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        
        while(sc.hasNextInt()){
            int n = sc.nextInt();
            int l = sc.nextInt();
            int[] index = new int[n];
            for(int i=0; i< n ;i++){
                index[i] = sc.nextInt();   
            }
            solve(n,l,index);
        }
    }
}

温故知新,未央书斋

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ambrosedream

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值