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

如何降低类背包变体子集优化问题的解决方案时间复杂度?

背包问题变体优化求解:动态规划+剪枝方案

问题定义

  • 给定由正整数元组(a, b)组成的列表,需挑选部分元素生成新列表,在满足阈值条件的前提下最大化选中元素的a值总和。
  • 阈值判断公式:((sumOfAllB × (weight − sharedWeight) + sharedWeight) / k) ≥ threshold,其中sumOfAllB是选中元素的b值总和,k是选中元素的数量,weight和sharedWeight为给定常量整数。
  • 当前暴力枚举的时间复杂度为O(2ⁿ),需要更高效的实现方式。

示例数据

const exampleQueue = [
  {a: 10, b: 4},
  {a: 7, b: 10},
  {a: 3, b: 6},
  {a: 1, b: 4},
  {a: 1, b: 1},
]
// 以下是几种选中状态(1表示选中,0表示未选中)
const mappedToA = [10, 7, 3, 1, 1] // 不满足阈值
const firstAttempt = [10, 7, 3, 1, 0]
const secondAttempt = [10, 7, 3, 0, 1]
const thirdAttempt = [10, 7, 3, 0, 0]
const fourthAttempt = [10, 7, 0, 1, 1]
// ...

优化方案:动态规划+剪枝

第一步:转化条件,缩小搜索范围

先把阈值公式变形简化:
原公式整理后可得:sumB*(weight - sharedWeight) ≥ k*threshold - sharedWeight
记C = weight - sharedWeight,D = -sharedWeight,公式可简化为:C*sumB + D ≥ k*threshold(若C=0需单独处理)

接着确定可选的元素数量范围:

  • 遍历k从1到总元素数n,找出所有可能的k值:排除那些无论选哪k个元素都无法满足阈值的情况,缩小后续搜索的范围。
  • 你提到的「计算需移除的最少元素数量」,本质是找到最大的有效k值(即n - 最少移除数),从这个k开始向下遍历——因为选中元素越多,a总和可能越大,优先检查高k值的情况能更快找到最优解。

第二步:动态规划状态设计

定义DP[k][s] = 选中k个元素时,能达到的最大a总和,其中s是这些元素的b值总和。

  • 状态转移:对每个元素(a_i, b_i),从当前最大可能的k值倒序遍历到1,再遍历所有已记录的s值,更新DP[k][s + b_i] = max(DP[k][s + b_i], DP[k-1][s] + a_i)。
  • 初始状态:DP[0][0] = 0,其余状态设为不可达(比如用-∞标记)。

第三步:剪枝与结果筛选

  • 同一k值下,若两个状态的s(b总和)相同,直接丢弃a总和较小的那个——我们的目标是最大化a,小值状态没有保留意义。
  • 遍历所有有效k值,对每个k检查DP[k]中的所有s是否满足阈值条件,记录满足条件的最大a总和。

时间复杂度说明

假设总元素数为n,最大有效k值为max_k,所有元素b值总和为max_sumB,则时间复杂度为O(n*max_k*max_sumB),远优于暴力枚举的O(2ⁿ),在n≤50的场景下完全可行。

补充提示

如果weight - sharedWeight为负数,阈值公式的不等号方向会反转,需要调整判断逻辑;若元素b值较大,可考虑对b值离散化,或用滚动数组优化DP的空间占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:04:50