0-1背包问题动态规划——代码注释详解

问题概述

0-1背包问题,其实就是给定若干个物体和一个可用于承物的背包。背包有一定的承重限制,而每个物体也有相应的重量和价值。“0-1”的意思就是物体只能选一次,核心问题在于如何在背包有限承重之下,使放入背包中的物体总价值最大。

代码实现

如果对这个问题还没有形成思路,安利下这个文章 0-1背包问题

from typing import List


def dp(weight: int, vals: List[int], weights: List[int]):
    """
    @brief 0-1背包问题DP解法
    @param weight  背包负重
    @param vals    物品价值列表
    @param weights 物品重量列表
    @return 所选物品的最大总价值
    """

    col = weight + 1                       
    row = len(vals)
    
    # 备忘录, 每行为考虑放入背包的物体。每列为背包的最大承重
    mmo = [ col * [0] for i in range(row)] 

    # 第i行均为考虑过放第i个物品到背包中,行数累加,表示考虑的物品范围增加了。
    # 如第1行表示,只考虑第1物品。第2行表示,同时考虑过第1、第2个物品。
    # 第j列表示承重只有j的背包下的最优解。
    
    # 只考虑第一个物品,只要能放入背包就拿走
    for j in range(1, col):
        if j >= weights[0]:
            mmo[0][j] = vals[0]

    # 考虑多个物品
    for i in range(1, row):
        # j 表示使用背包可承重。
        # 由于承重为0时,天然是最优情况,故从1开始迭代
        for j in range(1, col):
            if j >= weights[i]:
                # 既然,背包承重可以放下
                # 那么此时有两种选择
                # 1. j承重下,不放入当前物体
                # 2. j承重下,放入当前物体,同时放入剩余空间最优方案选择方案
                mmo[i][j] = max(
                    mmo[i-1][j],
                    vals[i] + mmo[i-1][j - weights[i]]
                )    
            else:
                # 单独放当前物体都放不下,只能放入先前的最优方案
                mmo[i][j] = mmo[i-1][j]
    
    return mmo[row - 1][col - 1]

ans = dp(4, [1500, 3000, 2000], [1, 4, 3])

后话

其实,在仔细观察后,可以发现只有当前计算行以及上一行会被使用到,其余的空间都是浪费的。对空间要求在苛刻一点,可以通过状态压缩只使用两行进行计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值