动态规划入门:01背包问题,提供模板和思路,简单易懂好上手(同时可在相应网站上做练习)

动态规划可以一般按照下面的步骤进行:
1)、状态定义;
2)、状态转移方程;
3)、初始化;
4)、输出;
5)、思考状态压缩。

01背包问题:

这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
1、题目描述:
https://www.acwing.com/problem/content/description/2/
在这里插入图片描述
在这里插入图片描述
2、题解:
在这里插入图片描述
用子问题定义状态:
即 dp[i][j] 表示前 i件物品恰放入一个容量为 j的背包可以获得的最大价值。
则其状态转移方程便是:dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i-1]]+w[i-1])。解释一下:
dp[i-1][j],不选第i-1个物品的背包的最大价值
dp[i-1][j-v[i-1]]+w[i-1],选第i-1个物品后的背包的最大价值(也即是剩余背包j-v[i-1]的容量的前i-1件物品,可以得到的最大价值+第i-1件物品的价值。
伪代码如下:

v[m]#体积数组
w[m]#价值数组
#初始化 ,m个物品,背包的总容量为n
dp[m+1][n+1]
dp[0][:] = 0
dp[:][0] = 0
for i in [1...m]:
    for j in [1...n]:
        dp[i][j] = max(dp[i-1][j],dp[i-1][j-v[i-1]]+w[i-1])
return dp[m][n]

上面的时间和空间复杂度都是O(m*n),下面将优化空间复杂度,将为O(n)
当然可以进行空间优化,这时候第二个循环,也就是内循环要倒着来
伪代码如下:

v[m]#体积数组
w[m]#价值数组
#初始化 ,m个物品,背包的总容量为n
dp[n+1]
dp[:] = 0
for i in [1...m]:
    for j in [n...1]:
        dp[j] = max(dp[j],dp[j-v[i-1]]+w[i-1])
return dp[n]

下面附上上面两个伪代码的python代码:注意处理边界
基础版:

m,n = map(int,input().split())
v = [] #体积数组
w = [] #价值数组

for i in range(m):
    num,x = map(int,input().split())
    v.append(num)
    w.append(x)
# print(m,n,v,w)
# dp = [[0] * (n+1)] * (m+1)
dp = [[0] * (n+1) for _ in range(m + 1)]
for i in range(1,m+1):
    for j in range(1,n + 1):
        if j < v[i-1]:
            dp[i][j] = dp[i-1][j]
        else:
            dp[i][j] = max(dp[i-1][j],dp[i-1][j-v[i-1]]+ w[i-1])
# print(dp)
print(dp[m][n])

优化版:

#空间优化
m,n = map(int,input().split())
v = [] #体积数组
w = [] #价值数组

for i in range(m):
    num,x = map(int,input().split())
    v.append(num)
    w.append(x)
# print(m,n,v,w)
# dp = [[0] * (n+1) for _ in range(m + 1)]
dp = [0 for _ in range(n + 1)]
for i in range(1,m+1):
    for j in range(n,0,-1):
        if j < v[i-1]:
            dp[j] = dp[j]
        else:
            dp[j] = max(dp[j],dp[j-v[i-1]]+ w[i-1])
# print(dp)
print(dp[n])

现在可以同步拿下LeetCode 416、474、494题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值