本文主要为了记载用,详细解释请自己根据提示亲自画图操作下,切忌眼高手低。

一、装满背包

装满背包,要求最红认定最大val值的前提是——此刻背包刚好装满,仅从实现上看,和“可不满”背包的区别只是初始化方法不同。以0-1背包为例,

V=10,N=3,c[]={3,4,5}, w={4,5,6}

1)背包不一定装满

      计算顺序是:从右往左,自上而下:因为每个物品只能放一次,前面的体积小的会影响体积大的基本背包问题

2)背包刚好装满    

      计算顺序是:从右往左,自上而下。注意初始值,其中-inf表示负无穷

基本背包问题

关于装满背包,读者可以自己体会下-inf作用,亲自划一下图,就明白为何如此初始化了。

参考自《经典背包问题 01背包+完全背包+多重背包

二、0-1背包

问题描述:有N件物品和一个容量为V的背包。第i建物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大

状态方程1:dp[i][j] = max{dp[i - 1][j], dp[i - 1][j - c[i] + w[i]]}

解决方案1:资料很多,此处从略。

状态方程2:优化空间,用f[v]代替dp[i][v]:max{f[v], f[v-c[i]] + w[i]}

for i  in 0 ... N  
    for  v = V ... 0  
        f[v] = max{f[v], f[v-c[i]] + w[i]}  

至于为什么v是从V到0,自己划一下才能明白。网上说法一大堆,不是自己的理解。

解决方法2:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
  
#define N 1010  
  
int value[N], volume[N], dp[N];  
  
// 0-1背包,优化空间  
void dpPackage(int n, int v)  
{  
    int i, j;  
  
    memset(dp, 0, sizeof(dp));  
  
    for (i = 1; i <= n; i ++) {  
        for (j = v; j >= volume[i]; j --) {  
                dp[j] = dp[j] > dp[j - volume[i]] + value[i] ? dp[j] : dp[j - volume[i]] + value[i];  
        }  
    }  
  
    printf("%d\n", dp[v]);  
}  
  
int main(void)  
{  
    int i, t, n, v;  
  
    scanf("%d", &t);  
  
    while (t --) {  
        // 接收参数  
        scanf("%d %d", &n, &v);  
  
        for (i = 1; i <= n; i ++)    scanf("%d", value + i);  
        for (i = 1; i <= n; i ++)    scanf("%d", volume + i);  
  
        // 0-1背包  
        dpPackage(n, v);  
    }  
  
    return 0;  
}  
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-06-22
猜你喜欢
  • 2022-12-23
  • 2021-10-25
  • 2022-01-03
  • 2021-12-07
  • 2022-12-23
  • 2021-12-15
  • 2022-12-23
相关资源
相似解决方案