You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何求解无限轴点选址及基于DP的路灯放置代码实现问题?

咱们先逐个解决你的两个问题,先从抽象的无限轴问题说起,再聚焦到实际的路灯规划动态实现上。

问题一:无限轴上选N个点使M个点的最近距离和最小

首先明确前提:我默认你说的是给定M个固定点,要在无限轴上选N个点(可任意位置),让每个M点到最近的N点的距离总和最小。如果理解有误,你可以补充说明~

最优解法分两步:

  • 第一步:把M个点按坐标从小到大排序。因为无限轴无边界限制,最优分组一定是连续的(如果分组不连续,比如把中间点分到左组、两边点分到右组,会额外增加距离和,连续分组是最优选择)。
  • 第二步:用动态规划将排序后的点划分成N个连续组,每组选中位数作为组的代表点,让各组的距离和总和最小。

为什么选中位数?这是经典结论:对于一组点,曼哈顿距离和最小的点就是该组的中位数。比如点[1,3,5],选3的距离和是4,选其他点的距离和都会更大。

动态规划核心逻辑

  • 状态定义:dp[i][k] 表示前i个M点,用k个选定点时的最小距离和。
  • 状态转移:dp[i][k] = min(dp[j][k-1] + cost(j+1, i)),其中j的范围是k-1 <= j < i(前j个点至少需要k-1个选定点,每组至少1个点),cost(a,b)表示第a到第b个M点组成一组,选中位数时的距离和。
  • 预处理cost数组:提前计算所有区间的距离和,避免重复计算,提升效率。
问题二:道路房屋路灯规划的动态实现

这个问题更具体:路灯必须安装在房屋位置,相邻房屋间距不同,我们用动态规划一步步实现最优解。

1. 问题转化与准备

首先将房屋位置整理成有序数组pos(道路上的房屋是线性排列的,提前按坐标排序),比如pos[0], pos[1], ..., pos[N-1],我们要选M个位置放路灯,让所有房屋到最近路灯的距离总和最小。

2. 动态规划核心设计

状态定义

dp[k][i] 表示用k盏路灯覆盖前i+1栋房屋(即pos[0]到pos[i])的最小距离和。

预处理cost数组

我们需要提前计算cost[a][b]:覆盖第a到第b栋房屋(0-based)用1盏路灯的最小距离和。根据中位数最优的结论,我们在a到b的房屋中选中位数位置放路灯,用前缀和快速计算距离和:

  • 先预处理前缀和数组prefix_sum,prefix_sum[i]表示pos[0]到pos[i-1]的坐标和,方便快速计算区间和。
  • 对于区间[a,b],找到中位数位置m = a + (b - a) // 2,计算:
    • 左边房屋到pos[m]的距离和:pos[m]*(m - a + 1) - (prefix_sum[m+1] - prefix_sum[a])
    • 右边房屋到pos[m]的距离和:(prefix_sum[b+1] - prefix_sum[m+1]) - pos[m]*(b - m)
    • cost[a][b]就是左右距离和的总和。

状态转移与初始化

  • 初始化:dp[1][i] = cost[0][i],表示用1盏路灯覆盖前i+1栋房屋的最小距离和。
  • 状态转移:对于k >= 2,dp[k][i] = min(dp[k-1][j] + cost[j+1][i]),其中j的范围是k-2 <= j < i(前j栋房屋用k-1盏路灯,至少需要k-1栋房屋)。
  • 最终答案:dp[M][N-1],即覆盖所有N栋房屋用M盏路灯的最小距离和。

3. Python代码实现示例

def min_streetlight_distance(pos, M):
    N = len(pos)
    pos.sort()  # 确保房屋位置按道路顺序排列
    # 预处理前缀和数组
    prefix_sum = [0] * (N + 1)
    for i in range(N):
        prefix_sum[i+1] = prefix_sum[i] + pos[i]
    
    # 预处理cost[a][b]:覆盖a到b栋房屋用1盏路灯的最小距离和
    cost = [[0] * N for _ in range(N)]
    for a in range(N):
        for b in range(a, N):
            # 找到区间[a,b]的中位数位置
            m = a + (b - a) // 2
            # 计算左边房屋到中位数的距离和
            sum_left = pos[m] * (m - a + 1) - (prefix_sum[m+1] - prefix_sum[a])
            # 计算右边房屋到中位数的距离和
            sum_right = (prefix_sum[b+1] - prefix_sum[m+1]) - pos[m] * (b - m)
            cost[a][b] = sum_left + sum_right
    
    # 初始化dp数组,初始值设为无穷大
    dp = [[float('inf')] * N for _ in range(M+1)]
    # 填充1盏路灯的情况
    for i in range(N):
        dp[1][i] = cost[0][i]
    
    # 填充多盏路灯的情况
    for k in range(2, M+1):
        # 至少需要k栋房屋才能放k盏路灯,所以i从k-1开始
        for i in range(k-1, N):
            # 前j栋房屋用k-1盏路灯,j至少为k-2(对应k-1栋房屋)
            for j in range(k-2, i):
                if dp[k-1][j] + cost[j+1][i] < dp[k][i]:
                    dp[k][i] = dp[k-1][j] + cost[j+1][i]
    
    return dp[M][N-1]

# 测试示例
pos = [1, 3, 5, 7, 9]
M = 2
print(min_streetlight_distance(pos, M))  # 输出:6

4. 优化思路

如果N很大(比如N>1000),O(MN²)的时间复杂度会超时,此时可以用四边形不等式优化(或Knuth优化),因为cost函数满足四边形不等式,能将时间复杂度降到O(MN),适合大规模数据场景。

内容的提问来源于stack exchange,提问作者K_peanutButter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:48:47