[算法与数据结构] - No.13 动态规划之完全背包

我们之前的那篇文章学习了什么是01背包,01背包的DP二维实现,DP一维实现。在这篇文章中我们学习完全背包问题:

完全背包和01背包的区别在于,01背包每个物品只有一个,所以每个物品只有装和不装两个选择,但是在完全背包中,每个物品数量都是无穷个,所以可以随便选取。即:

有 N 种物品和一个容量为 V 的背包,每种物品都有无限件可用。放入第 i 种物品的费用是 Ci,价值是 Wi。求解:将哪些物品装入背包,可使这些物品的耗费的费用总
和不超过背包容量,且价值总和最大

我们找到的状态转移方程为:

F [i,v] = max { F [i − 1,v − kCi] + kWi | 0 ≤ kCi ≤ v } 

我们将上面的k分别选为0 和1,即为我们的01背包的状态转换式。同理,我们的完全背包也可以写为一维数组实现:

F [0...V ] 0
for i = 1 to N
for v = Ci to V
F [v] = max(F [v],F [v − Ci] + Wi)

不知大家注意到没有,在01背包中,我们为了保证F [v] 是由之前的F [i − 1,v − Ci]递推而来,而不是F [i ,v − Ci]递推而来(其实就是防止在背包中多次放入一个物品),我们对于容量v的遍历是从后往前的逆序(详见本文

但是,在这里,我们是从前往后的顺序,因为没有了物体只有一个的约束:

我们还以采药的题目(5938: 【基础背包入门3】第二次 采药)为例子:

#include <iostream>
using namespace std;


int main()
{
    int dp[1002];
    int v[120];
    int w[120];
    int T,M;
    while(cin >>T>>M&&T>0&&M>0)
    {
        for(int i = 1; i<=M; i++)
        {
            cin>>v[i]>>w[i];
        }
        for(int j = 0; j<=T; j++)
        {
            dp[j] = 0;
        }
        for(int i = 1; i <= M; i++)
        {

            for(int j = 0; j<=T; j++)
            {
                if(j>=v[i]&&dp[j]<dp[j-v[i]]+w[i])
                {
                    dp[j] = dp[j-v[i]]+w[i];
                }
            }
        }
        cout<<dp[T]<<endl;
    }
    return 0;
}
所以,在背包中,我们推荐使用一维数组的实现形式,简单又好记

P.S.文章不妥之处还望指正


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值