《算法图解》背包问题(二维与三维背包问题)

背包问题,最大利润

《算法图解》背包问题(二维与三维背包问题)_第1张图片这是一个典型的背包问题,应当注意这个每样物品是否可以重复取用。
我们可以绘制dp表格,从子问题下手。恰当的选择子问题。

当只有水可以选择时,背包容量为[1,6]时可以最大多少。
当水,和书都可以选择时,背包最大多少

因此,dp表格的行是不同的选择范围,列是不同的背包容量下的最优解。

    def bag(self, bag, val, n):
    # bag 是东西的大小,val是价值,n是容量
        dp = [[0 for i in range(n+1)]for i in range(len(val)+1)]
        # 列是容量 行是可拿东西
        for i in range(1, len(val)+1):
            for j in range(1, n+1):
            	# 当放不下当前物品时,考虑没有当前物品的最大可能
                if bag[i-1] > j:
                    dp[i][j] =  dp[i-1][j]
                else: # 如果可以放开,就比较放和不放时那样收益最大
                    dp[i][j] = max([i-1][j], dp[i-1][j-bag[i-1]]+val[i-1])
                  
        return dp[-1][-1]

这是考虑的最优解是背包装的是可重复的,也就是可能装了一包的相机

以下内容写错了,我还是想复杂了问题。
本质上的转移方程可以更优的,我只需要dp[i][j] = max([i-1][j], dp[i-1][j-bag[i-1]]+val[i-1])就可以避免重复。。。


2020.03.28更新

我还是想复杂了,这个方法的空间复杂度还是可以进一步压缩的。状态的i其实可以去掉,因为只和i-1有个,只要我们倒序迭代就可以解决这一问题。

    def bag_simple(self, bag, val,n):
        dp = [0]*(n+1)
        for i in range(len(bag)):
            for j in range(n, , -1):
                if j>=bag[i]:
                    dp[j] = max(dp[j], dp[j-bag[i]]+val[i])
        return dp[n]

但是还一种可能是每种物品只有一件,也就是包里的东西是不能重复的。这就要求我们增加一个状态,表明当前这个物品是否已经装进去了,如果装进去了就不能重复装了。
dp表格变为3维的。

    def bag(self, bag, val, n):
        dp = [[[0 for i in range(n+1)]for i in range(len(val)+1)] for i in range(2)]
        # 第一维是是否装入当前物品,第二维是可拿的东西 第三位是容量
        # 注意这个与初始化dp的循环是反的
        for i in range(1, len(val)+1):
            for j in range(1, n+1):
            	# 装不进去,就是不考虑当前物品时,上一个的最大值
                if bag[i-1] > j:
                    dp[0][i][j] = max(dp[0][i-1][j], dp[1][i-1][j])
                else:
                #分别考虑装了和没装,写清楚状态转移方程就不难
                    dp[0][i][j] = max(dp[0][i-1][j], dp[1][i-1][j])
                    dp[1][i][j] = dp[0][i][j-bag[i-1]]+val[i-1]
        return max(dp[1][i][j], dp[0][i][j])

你可能感兴趣的:(《算法图解》背包问题(二维与三维背包问题))