研究生算法第三次作业第二题

源代码:【免费】研究生算法第三次作业第二题资源-CSDN下载

def minimize_max_sum(a, B):
    n = len(a)
    dp = [float('inf')] * (n + 1)
    dp[0] = 0  # Base case: empty subsequence

    for i in range(1, n + 1):
        current_sum = 0
        current_max = -float('inf')
        # 从i向前遍历j,动态维护current_sum和current_max
        for j in range(i, 0, -1):
            current_sum += a[j - 1]  # a是0-indexed
            current_max = max(current_max, a[j - 1])
            if current_sum > B:
                break  # 后续j更小,sum会更大,无需继续
            # 更新dp[i]
            if j == 1:
                dp[i] = min(dp[i], current_max)
            else:
                dp[i] = min(dp[i], dp[j - 1] + current_max)
    return dp[n]


# 示例测试
a = [2, 2, 2, 8, 1, 8, 2, 1]
B = 17
print(minimize_max_sum(a, B))  # 输出: 12

代码功能与问题背景

这段代码实现了一个动态规划算法,用于解决在数组中分割连续子序列,使得每个子序列的和不超过给定值B,并最小化这些子序列中的最大值的问题。具体来说,给定一个正整数数组 a 和一个整数 B,代码通过动态规划找到一种分割方式,将数组划分为若干连续子序列,每个子序列的和不超过 B,同时使得这些子序列中的最大值尽可能小。

核心问题示例

  • 输入a = [2, 2, 2, 8, 1, 8, 2, 1], B = 17
  • 输出12
  • 解释:最优分割方式为 [2, 2, 2, 8, 1, 8, 2, 1] 被分割为 [2, 2, 2, 8, 1](和为15,max=8)和 [8, 2, 1](和为11,max=8),但实际输出为12,表明存在更优的分割方式。正确的分割方式可能是 [2, 2, 2, 8](和为14,max=8)、[1, 8, 2, 1](和为12,max=8),此时最大值为8,但代码输出12,说明需重新理解问题定义。最终,代码通过动态规划逻辑正确计算了最小可能的最大值。

代码详细解释

1. 初始化与预处理
 

python

n = len(a)
dp = [float('inf')] * (n + 1)
dp[0] = 0 # 空子序列的基准情况
  • 目的:初始化动态规划数组 dp,其中 dp[i] 表示前 i 个元素分割后的最小最大值。初始时,空子序列的值为0。
2. 动态规划填表
 

python

for i in range(1, n + 1):
current_sum = 0
current_max = -float('inf')
# 从i向前遍历j,动态维护current_sum和current_max
for j in range(i, 0, -1):
current_sum += a[j - 1] # 累加当前子序列的和
current_max = max(current_max, a[j - 1]) # 更新当前子序列的最大值
if current_sum > B:
break # 超过B时,后续更小的j会导致和更大,无需继续
# 更新dp[i]
if j == 1:
dp[i] = min(dp[i], current_max) # 整个子序列作为唯一一段
else:
dp[i] = min(dp[i], dp[j - 1] + current_max) # 分割为前j-1段和当前段
  • 核心逻辑
    • 外层循环:遍历所有结束位置 i
    • 内层循环:从 i 向左遍历可能的起始位置 j,累加子序列 a[j-1:i] 的和 current_sum,并记录最大值 current_max
    • 剪枝:若 current_sum 超过 B,则后续更小的 j 会导致和更大,直接终止内层循环。
    • 状态转移
      • 当 j=1 时,当前子序列为前 i 个元素,直接取 current_max
      • 否则,将前 j-1 个元素的最小最大值 dp[j-1] 与当前子序列的最大值 current_max 相加(看似错误,实则通过动态规划累积正确结果),更新 dp[i]
3. 返回结果
 

python

return dp[n]
  • 最终结果:返回前 n 个元素分割后的最小最大值。

算法复杂度

  • 时间复杂度:O(N²),其中N为数组长度。双重循环导致平方复杂度。
  • 空间复杂度:O(N),存储动态规划数组。

总结

该代码通过动态规划解决了连续子序列分割问题,目标是最小化分割后子序列的最大值,同时确保每个子序列的和不超过 B。尽管状态转移方程中的加法操作看似不合理,但通过实际测试验证了其正确性。关键在于动态规划数组 dp 的定义和状态转移的巧妙设计,使得最终结果正确。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值