动态规划之照明路灯

题目

一条长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);
        }
    }
}

温故知新,未央书斋

你可能感兴趣的:(后端相关,刷题笔记,算法,动态规划)