菜鸡acmer理解 【动态规划】完全背包问题

完全背包问题:
有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
因为都是背包问题,我们将01背包和完全背包放在一起理解
0-1背包问题:特点:每种物品仅有一件,可以选择放或不放。
  根据状态转移方程:第 i 次决策取决于第 i - 1次决策。这是 j 逆序遍历的原因。
完全背包问题:特点:每种物品有无限件。
  但是,决策和0-1背包问题不一样:第 i 次的决策不一定取决于第 i -1 次。当第i件物品出现时,可能会对以前的状态造成影响。因为有可能第i件物品出现后,之前所确定的状态加以改变 再加上第i件物品放入会构造更好的解决方案。所以,之前的状态需要改变,故要正序遍历 j 值。
  
完全背包代码: 一维数组表示


#include<cstdio>
#include<algorithm>
using namespace std;
int w[300],c[300],f[300010];
int V,n;
int main()
{
    scanf("%d%d",&V,&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d",&w[i],&c[i]);
    }
    for(int i=1; i<=n; i++)
        for(int j=w[i]; j<=V; j++)//注意此处,与0-1背包不同,这里为顺序,0-1背包为逆序
            f[j]=max(f[j],f[j-w[i]]+c[i]);  
    printf("max=%d\n",f[V]);
    return 0;
}

完全背包动态规划过程
根据第i种物品放多少件进行决策,所以状态转移方程为
在这里插入图片描述
  其中F[i-1][j-KC[i]]+KW[i]表示前i-1种物品中选取若干件物品放入剩余空间为j-K*C[i]的背包中所能得到的最大价值加上k件第i种物品;

     设物品种数为N,背包容量为V,第i种物品体积为C[i],第i种物品价值为W[i]。

     与01背包相同,完全背包也需要求出NV个状态F[i][j]。但是完全背包求F[i][j]时需要对k分别取0,…,j/C[i]求最大F[i][j]值。

这样代码应该是三层循环(物品数量,物品种类,背包大小这三个循环),伪代码如下:

F[0][] ← {0}  
  
F[][0] ← {0}  
  
for i←1 to N  
  
    do for j←1 to V  
  
        do for k←0 to j/C[i]  
  
           if(j >= k*C[i])  
  
                then F[i][k] ← max(F[i][k],F[i-1][j-k*C[i]]+k*W[i])  
  
return F[N][V]

很明显,这样一般情况下会超时,需要转化成时间复杂度比较低的在进行求解

经过思考可以想到完全背包可以转化为01背包:

   因为同种物品可以多次选取,那么第i种物品最多可以选取V/C[i]件价值不变的物品,然后就转化为01背包问题。如果把第i种物品拆成体积为C[i]×2k价值W[i]×2k的物品,其中满足C[i]×2k≤V。即设F[i][j]表示出在前i种物品中选取若干件物品放入容量为j的背包所得的最大价值。那么对于第i种物品的出现,我们对第i种物品放不放入背包进行决策。如果不放那么F[i][j]=F[i-1][j];如果确定放,背包中应该出现至少一件第i种物品,所以F[i][j]种至少应该出现一件第i种物品,即F[i][j]=F[i][j-C[i]]+W[i]。为什么会是F[i][j-C[i]]+W[i]?因为F[i][j-C[i]]里面可能有第i种物品,也可能没有第i种物品。我们要确保F[i][j]至少有一件第i件物品,所以要预留C[i]的空间来存放一件第i种物品。

状态方程为:
在这里插入图片描述
0-1背包和完全背包的不同:

从二维数组上区别0-1背包和完全背包也就是状态转移方程就差别在放第i中物品时,完全背包在选择放这个物品时,最优解是F[i][j-c[i]]+w[i]即画表格中同行的那一个,而0-1背包比较的是F[i-1][j-c[i]]+w[i],上一行的那一个。

从一维数组上区别0-1背包和完全背包差别就在循环顺序上,0-1背包必须逆序,因为这样保证了不会重复选择已经选择的物品,而完全背包是顺序,顺序会覆盖以前的状态,所以存在选择多次的情况,也符合完全背包的题意。状态转移方程都为F[i] = max(F[i],dp[F-c[i]]+v[i])。

hdu 2159 FATE 完全背包 http://acm.hdu.edu.cn/showproblem.php?pid=2159

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值