0-1背包问题

给定n种物品: 

物品i的重量是wi,其价值为vi。 

和一个背包: 

背包的容量为C。 

在选择装入背包的物品时,对于每种物品i只有两种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。 

 

 

首先:带备忘录的递归方法: 

我们利用F(n, C)表示将前n个物品放入容量为C的背包里,得到的最大价值。 

推导:使用自顶向下的思想,假如我们已经进行到最后一步(即求解将第n个物品放到背包里获得的最大价值), 

    此时我们有两种选择: 

        1.不放第n个物品:此时总价值为F(n - 1, C) 

        2.放置第n个物品:此时总价值为vn + F(n, c - wn) 

/* 

    根据递归公式F(i, c) = max{F(i - 1, c), vi + F(i, c - wi)} 

    其中i为第i个物品,c为背包重量,vi为第i个物品的价值,wi为第i个物品的重量 

    Args: 

        w 物品的重量数组 

        v 物品的价值数组 

        index 当前带选择的物品的索引 

        capacity 当前背包有效容量 

    return: 

        最大价值 

*/ 

 

上述方法实现了带备忘录的递归方法,即不用多次求解子问题。 

 

动态规划方法 规划的条件依然是物品的下标i和背包的容量capacity: 

 

 

动态规划算法通过状态转移方程直接构建dp数组 

 

其中第一行要先确定,即将第一个物品在容量分别为0-capacity时存入数组,随后根据上一个物品决定新的物品是否放入背包。 

 

 

 

上述代码也可以从1开始保存。即id为0时认为没有物品。 

即将备忘录改为: 

同时初始化代码改为: 

 

 

代码可进行优化,因为我们发现dp[i][j]中的i只与上一行有关,所以我们可以把二维数组变为一位数组,只存上一行保存的数据。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值