动态规划 - 01背包

动态规划 - 01背包

来源: https://www.acwing.com/problem/content/2/

题目描述:

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

第 i 件物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。


动态规划分析分为:状态计算、状态表示

状态表示f[i][j]:

  • 集合: 前i个物品,取得体积不超过j的价值
  • 属性: Max

状态计算:

  • 以取第i件物品和不取第i件物品进行划分
  • 不取第i件物品,那么f[i][j] = f[i - 1][j - 1]
  • 取第i件物品,等于减去当前物品的容量,加上当前物品的价值。f[i][j] = f[i][j - v[i]] + w[i]

所以伪代码如下:

for i <- 0 to n:
    for j <- 0 to m:
        f[i][j] = f[i - 1][j]
        if v[i] <= j:
            f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i])

具体Python代码实现如下:

N = 1010
dp = [[0]*N for _ in range(N)]
v = [0]*N
w = [0]*N

def main():
    n, m = map(int, input().split())
    for i in range(1, n + 1):
        v[i], w[i] = map(int, input().split())
        
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            dp[i][j] = dp[i - 1][j]
            if j >= v[i]:
                dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i])
    
    print(dp[n][m])
    
    
main()

据dp表格所推出来的数据如下, 行表示物品i, 列表示背包容量v

012345
000000
022222
024666
024668
024668

由状态转移方程可以看出,f[i][j]都是来自于第i-1层的数据,这时就可以使用可以利用一层空间进行状态的记录,我们只需要从大到小的枚举, 那么f[j - v[i]]的状态就是f[i - 1][j - v[i]]的状态。

伪代码如下:

for i <- 1 to n:
    for j <- v to v[i]:
        f[j] = max(f[j], f[j - v[i] + w[i])

因为使用一维状态,那么f[j] = f[i - 1][j]保持着上次的数据,这时就只需要枚举到v[i]。但是在二维背包中,f[i][j]默认是0,每层的背包都需要跟新,所以背包容量j从0开始枚举到m。

具体Python代码如下:

N = 1010
dp, v, w = [0]*N, [0]*N, [0]*N


def main():
    n, m = map(int, input().split())
    for i in range(1, n + 1):
        v[i], w[i] = map(int, input().split())
        
    for i in range(1, n + 1):
        for j in range(m, v[i] - 1, -1):
                dp[j] = max(dp[j], dp[j - v[i]] + w[i])
    
    print(dp[m])
    
    
main()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值