动态规划——背包问题

动态规划——背包问题

  • 背包问题
    • 0-1背包
      • 问题描述
      • 解题思路
      • 优化
    • 完全背包
      • 解题思路
      • 优化
    • 多重背包
      • 解题思路1
      • 解题思路2
    • 恰好装满
      • 问题描述
      • 解题思路
      • 优化

背包问题

0-1背包

一共有n件物品,第i(i从1开始)件物品的重量为w[i],价值为v[i]。在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值是多少?

问题描述

假如你要去野营,你有一个容量为6磅的背吧,需要觉得该携带下面的哪些东西。其中每样东西都有相应的价值,价值越大意味着越重要。

  • 水(重3磅,价值10);
  • 书(重1磅,价值3);
  • 食物(重2磅,价值9);
  • 夹克(重2磅,价值5);
  • 相机(重1磅,价值6)。

请问携带哪些东西时价值最高?

解题思路

dp[i][j]表示只看前i个物品,总体积是j的情况下,总价值最大是多少

  • 不选第i个物品:f[i][j]=f[i-1][j]
  • 选第i个物品:f[i][j]=f[i-1][j-v(i)]+w[i],在两者之间选取大值。

初始化,f[0][0]=0,表示什么都没装,价值也为0.
计算得表格:

0 1 2 3 4 5 6
0 0 10 10 10 10
3 3 10 13 13 13
食物 3 9 12 13 19 22
夹克 3 9 12 14 19 22
相机 6 9 15 18 20 25

Python代码:

n, v = map(int,input().split())
goods = []
for i in range(n):
    goods.append([int(i) for i in input().split()])
dp = [[0 for j in range(v+1)] for i in range(n)]
for i in range(n):  # 物品ID
    for j in range(1, v+1):  # 表格中的纵轴,1,2,3,4,5,6
        if goods[i][0]<=j:
            dp[i][j] = max(goods[i][1]+dp[i-1][j-goods[i][0]], dp[i-1][j])
        else:
            dp[i][j] = dp[i-1][j]
print(dp[-1][-1])

输出:

25

优化

根据代码可以看出整个过程都只和上一层有关,和前面的无关,因此可以考虑将dp转化为只有一层的。但这里需要注意的是不能从前往后,会导致dp[j-goods[i][0]]变化,因此要倒序。

n, v = map(int, input().split())
goods = []
for i in range(n):
    goods.append([int(i) for i in input().split()])
dp = [0 for i in range(v+1)]
for i in range(n):
    for j in range(v, -1, -1):
        if goods[i][

你可能感兴趣的:(动态规划,算法)