我如何解决 0-1 背包算法的这些变体?

Posted

技术标签:

【中文标题】我如何解决 0-1 背包算法的这些变体?【英文标题】:How do i solve these variations of the 0-1 knapsack algorithm? 【发布时间】:2016-07-21 22:04:01 【问题描述】:

背包可以承载最大重量,比如 max_wt ;有 n 个具有给定权重wt[] 和值val[] 的项目。我有两个问题(彼此分开):

如果我们可以携带的体积有第二个限制 vol[],我们可以携带的最大值是多少? 有多少种方法可以准确地携带 z(

我的尝试

对于第一个问题,我提到了this*** 帖子,但我能理解的唯一答案是两个约束合并的地方,但我猜它的运行时间复杂度会很大......我在想的是制作一个dp[i][j][k],其中 i 是选择的项目数,j 是当时选择的 max-wt,k 是当时选择的 max-vol,然后我的代码核心看起来像for(i=0 ; i < n ; i++) \\ n is no. of items for(j=0 ; j < n ; j++) for(k=0 ; k < n ; k++) dp[i][j][k] = max( dp[i-1][j][k] , val[i] + dp[i-1][j-wt[j]][k-vol[k]]) ; ,这似乎没问题,但给了我错误的答案......我猜不出为什么:(

我无法开始思考第二个问题,我的朋友通过采取三个状态 dp[i][j][k] 做到了,其中 i 和 j 与第一个问题相同(通常的) 虽然 'k' 跟踪所选项目的总数,但这个想法并没有出现在我的脑海中。另外,状态将存储什么,它通常存储可能的最大值,直到经典背包问题中的给定状态,这里我猜一个状态将存储可被 8 整除的总组合直到该状态,但我无法将其转换为代码。

p.s 请尝试为第二个问题提供自下而上的解决方案,我对动态编程非常陌生。 ;)

【问题讨论】:

最大的路数是多少... - 你是指路数吗?如果不是,最大值指的是什么? “这样它们的总和可以被一个数整除” - 什么的总和?重量/体积还是其他? 对不起,我的问题还不清楚,这里又是一个完整的问题:给定 var[ ] , wt[ ] of n 个项目,我们如何为我们的背包准确选择 z( @DanielRodriguez sum of value ,只是第二个问题没有体积限制的值 @Gassa 我措辞错误..我的意思只是方式的数量...谢谢你挑出来 【参考方案1】:

二维背包问题

n 为项目数 让val[i]i-th 项的值 设w[i]i-th 项的权重 设v[i]i-th item的音量 让T[i,j,k] 成为第一个i 项目中的最佳价值,并且具有精确 重量j 和体积kT 可以用其他方式定义,但这个定义给出了一个简短的公式。

寻找最佳价值

T[0,j,k] = 0

T[i,j,k] = T[i-1,j,k],当j&lt;w[i]k&lt;v[i],否则:

T[i,j,k] = max( T[i-1,j,k] , T[i-1,j-w[i],k-i] + val[i] )

对于所有 j 和 k,最佳可能值是 max T[n,j,k]

实施说明

首先为所有 jk 初始化基本情况

从 1 到 n 循环 i 并与基于 1 的数组索引保持一致

循环 j 从 1 到最大可能权重,这是所有权重的总和,例如w[1]+w[2]+...w[n]

循环 k 从 1 到最大可能音量

用精确的项目数计算获得精确值的方法数

S[i,j,k,l] 是第一个i 项目可以按照重量j、价值kl 项目排列的方式数。

李>

S[0,j,k,l] = 0S[0,0,0,0] = 1 除外

S[i,j,k,l] = S[i-1,j,k,l] + S[i-1,j-w[i],k-val[i],l-1]

精确使用 z 项获得精确值 y 的方法数是所有 jT[n,j,y,z] 的总和

观察

有很多方法可以查看这些问题并定义状态 T 和 S。这只是其中之一。实现也可以不同。维度的经验法则是 sack 中的另一个约束或项目中的维度意味着公式中的另一个维度。计算方式的经验法则是加起来而不是找到最大值。

【讨论】:

第二个问题 q 调用“数字...(例如 8)”。您可以通过将 k 限制在 0 .. q-1 范围内并对 k mod q 执行所有算术运算来节省第二个 DP 中的内存。 很好的答案...尽管请您解释一下最后一行...我不明白S[i,j,k,l] = S[i-1,j,k,l] + S[i-1,j-w[i],k-val[i],l-1]如何计算方式总数....据我了解,您做了[0,0,0,0] 等于 1,因此每当达到该状态时,计数的数量就会增加,但我不确定我是否正确。加上T[ ]S[ ]有什么区别,第二个问题没有提到T[ ]...? S[i,j,k,l] 要么有 i-th 项目,要么没有。到达状态 (i,j,k,l) 的方式数是使用i-th 项到达那里的方式数加上不使用i-th 项到达那里的方式数.计数问题不关心最大化值(T),只关心获得特定值的方法的数量,这就是为什么值是一个维度。

以上是关于我如何解决 0-1 背包算法的这些变体?的主要内容,如果未能解决你的问题,请参考以下文章

背包算法的变体

背包算法变体

背包问题变体的递归关系?

0-1背包的贪心算法

Java遗传算法解决0-1背包问题

背包问题变体 - 将重量和价值最大化到极限