解题思路

这是一个二分查找问题。需要找到最小的灯光覆盖距离d,使得所有路灯能够覆盖整条街道。

关键点:

  1. 对路灯位置进行排序
  2. 使用二分查找确定最小覆盖距离
  3. 检查给定距离是否可以覆盖整条街
  4. 处理精度问题

算法步骤:

  1. 对路灯位置排序
  2. 二分查找最小覆盖距离
  3. 验证覆盖的可行性
  4. 输出保留两位小数的结果

代码

#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    // 检查给定的覆盖距离是否可行
    bool check(vector<int>& lights, int l, double d) {
        if (lights[0] > d) return false;  // 检查起点
        
        double covered = lights[0] + d;
        for (int i = 1; i < lights.size(); i++) {
            if (lights[i] - d > covered) return false;
            covered = lights[i] + d;
        }
        
        return covered >= l;  // 检查终点
    }
    
    double solve(int n, int l, vector<int>& lights) {
        // 对路灯位置排序
        sort(lights.begin(), lights.end());
        
        // 二分查找最小覆盖距离
        double left = 0, right = l;
        while (right - left > 1e-5) {  // 精度控制
            double mid = (left + right) / 2;
            if (check(lights, l, mid)) {
                right = mid;
            } else {
                left = mid;
            }
        }
        
        return left;
    }
};

int main() {
    int n, l;
    while (cin >> n >> l) {
        vector<int> lights(n);
        for (int i = 0; i < n; i++) {
            cin >> lights[i];
        }
        
        Solution solution;
        printf("%.2f\n", solution.solve(n, l, lights));
    }
    
    return 0;
}
import java.util.*;

public class Main {
    static class Solution {
        // 检查给定的覆盖距离是否可行
        private boolean check(int[] lights, int l, double d) {
            if (lights[0] > d) return false;  // 检查起点
            
            double covered = lights[0] + d;
            for (int i = 1; i < lights.length; i++) {
                if (lights[i] - d > covered) return false;
                covered = lights[i] + d;
            }
            
            return covered >= l;  // 检查终点
        }
        
        public double solve(int n, int l, int[] lights) {
            // 对路灯位置排序
            Arrays.sort(lights);
            
            // 二分查找最小覆盖距离
            double left = 0, right = l;
            while (right - left > 1e-5) {  // 精度控制
                double mid = (left + right) / 2;
                if (check(lights, l, mid)) {
                    right = mid;
                } else {
                    left = mid;
                }
            }
            
            return left;
        }
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int n = sc.nextInt();
            int l = sc.nextInt();
            
            int[] lights = new int[n];
            for (int i = 0; i < n; i++) {
                lights[i] = sc.nextInt();
            }
            
            Solution solution = new Solution();
            System.out.printf("%.2f\n", solution.solve(n, l, lights));
        }
        sc.close();
    }
}
class Solution:
    def check(self, lights, l, d):
        # 检查给定的覆盖距离是否可行
        if lights[0] > d:  # 检查起点
            return False
            
        covered = lights[0] + d
        for i in range(1, len(lights)):
            if lights[i] - d > covered:
                return False
            covered = lights[i] + d
            
        return covered >= l  # 检查终点
    
    def solve(self, n, l, lights):
        # 对路灯位置排序
        lights.sort()
        
        # 二分查找最小覆盖距离
        left, right = 0, l
        while right - left > 1e-5:  # 精度控制
            mid = (left + right) / 2
            if self.check(lights, l, mid):
                right = mid
            else:
                left = mid
                
        return left

# 持续读取输入直到EOF
while True:
    try:
        n, l = map(int, input().split())
        lights = list(map(int, input().split()))
        
        solution = Solution()
        print("{:.2f}".format(solution.solve(n, l, lights)))
    except EOFError:
        break

算法及复杂度

  • 算法:二分查找
  • 时间复杂度:,其中 是路灯数量, 是街道长度
  • 空间复杂度:,不考虑输入数组