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

时间:2016-07-21 22:04:02

标签: c++ algorithm dynamic-programming knapsack-problem

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

  • 如果我们可以携带的音量有第二个限制,我们可以携带的最大值是什么,vol []?
  • 携带总共z(&n; n)个项目的方式有多少,以便它们的值总和可被数字整除,比如8?

我的尝试

  • 对于第一个问题,我提到了this stackoverflow post,但我能理解的唯一答案是合并了两个约束的那个,但我认为运行时复杂度会非常大。 ..我想的是制作dp[i][j][k],其中i是所选项目的数量,j是在该点选择的最大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整除的总组合直到该状态,但我不能将其转换为代码。

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

1 个答案:

答案 0 :(得分:2)

二维背包问题

  • n成为项目数
  • val[i]成为i - 项目
  • 的值
  • w[i]成为i项目
  • 的权重
  • v[i]成为i项目
  • 的数量
  • T[i,j,k]成为第一个i项目中的最佳价值,并且完全权重j和量kT可以用其他方式定义,但这个定义给出了一个简短的公式。

寻找最佳价值

  • T[0,j,k] = 0

  • T[i,j,k] = T[i-1,j,k]j<w[i]k<v[i]时,否则:

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

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

实施说明

  • 首先为所有jk

  • 初始化基本案例
  • 循环i从1到n并与基于1的数组索引一致

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

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

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

  • S[i,j,k,l]成为可以使用正确权重i,值j和{{1}排列第一个k项目的方式数量物品。

  • lS[0,j,k,l] = 0

  • 除外
  • S[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]项准确获取价值y的方法数量是所有z

  • T[n,j,y,z]的总和

观察

有很多方法可以查看这些问题并定义状态T和S.这只是其中之一。实现也可能不同。尺寸的拇指规则是袋中的另一个约束或项中的尺寸表示公式中的另一个尺寸。计算方式的缩略规则是你加起来而不是找到最大值