完全背包

完全背包

背包容量为 V V V,有 n n n种物品,每种物品有无限多个,第 i i i种物品体积为 c i c_i ci,价值为 w i w_i wi,怎样装填背包使总价值最大?

实际上,完全背包并不代表每种物品可以真正装填“无限”多个,因为存在背包总体积这一限制因素。

分析:闫氏DP分析法

  • 状态表示

    • 集合:定义数组 d p [ i ] [ j ] dp[i][j] dp[i][j],表示当前选取方案的价值。第 i i i行表示只考虑前 i i i种物品的放置情况, j j j表示当前选取体积不超过 j j j的方案集合。 i n i t ( d p [ 0 ] [ i ] , d p [ j ] [ 0 ] ) = 0 init(dp[0][i],dp[j][0])=0 init(dp[0][i],dp[j][0])=0
    • 属性: M a x Max Max
  • 状态计算: d p [ i ] [ j ] dp[i][j] dp[i][j]:对于第 i i i种物品:

    • 不可选第 i i i种物品:当 v < c [ i ] v<c[i] v<c[i]时,无法装入背包,背包剩余容积不变。集合状态仍为 [ 1 , i − 1 ] [1,i-1] [1,i1],直接继承自第 i − 1 i-1 i1种物品且背包容积仍为 j j j方案的价值。 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j] dp[i][j]=dp[i1][j]
    • 可选第 i i i种物品:
      • 不选第 i i i种物品:若选第 i i i种物品无法保证最优解,则不选,背包剩余容积不变。集合状态仍为 [ 1 , i − 1 ] [1,i-1] [1,i1],直接继承自第 i − 1 i-1 i1种物品且背包容积仍为 j j j方案的价值。 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j] dp[i][j]=dp[i1][j]
      • [ 1 , . . . , k , . . . + ∞ ] [1,...,k,...+\infty] [1,...,k,...+]个第 i i i种物品:选第 i i i种物品可能导致产生最优解,则选。集合状态变为 [ 1 , i ] [1,i] [1,i],因为第 i i i种物品可被选多次,设选 k k k个第 i i i种物品,则继承自第 i i i种物品且背包容积 j j j减少 k ∗ c [ i ] k*c[i] kc[i]方案的价值,并加 k ∗ w [ i ] k*w[i] kw[i]。对于每一次选第 i i i种物品,为 d p [ i ] [ j ] = d p [ i ] [ j − c [ i ] ] + w [ i ] dp[i][j]=dp[i][j-c[i]]+w[i] dp[i][j]=dp[i][jc[i]]+w[i]
  • 状态转移方程式: d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − c [ i ] ] + w [ i ] ) dp[i][j]=max(dp[i-1][j],dp[i][j-c[i]]+w[i]) dp[i][j]=max(dp[i1][j],dp[i][jc[i]]+w[i])

遍历顺序:物品和背包谁先遍历都可以

void init(){
    for(int i=0;i<=n;i++) dp[i][0]=0;
    for(int i=0;i<=v;i++) dp[0][j]=0;
}
void dp(){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=v;j++)
            if(c[j]<v) dp[i][j]=max(dp[i-1][j],dp[i][j-c[i]]+w[i]);
    		else dp[i][j]=dp[i-1][j];
}

时间复杂度 O ( n 3 ) O(n^3) O(n3),空间复杂度 O ( n v ) O(nv) O(nv)

滚动优化

交替滚动

extern int dp[2][v];
void dp(){
    int work=0,old=1;
    for(int i=1;i<=n;i++){
        swap(work,old);
        for(int j=1;j<=v;j++)
            if(c[i]<=j) dp[work][j]=max(dp[old][j],dp[work][j-c[i]]+w[i]);
    		else dp[work][j]=dp[old][j];
    }
}

自我滚动

遍历顺序:物品背包谁先遍历都可以,且均为顺序遍历

extern int dp[v];
void dp(){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=v;j++)
            dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
}

相关推荐

  1. 完全背包

    2024-07-16 00:02:05       17 阅读
  2. 01背包完全背包

    2024-07-16 00:02:05       40 阅读
  3. 完全背包总结二

    2024-07-16 00:02:05       42 阅读
  4. 完全背包详解--模板

    2024-07-16 00:02:05       59 阅读
  5. 动态规划09-完全背包

    2024-07-16 00:02:05       53 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 00:02:05       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 00:02:05       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 00:02:05       58 阅读
  4. Python语言-面向对象

    2024-07-16 00:02:05       69 阅读

热门阅读

  1. 【C语言】字符常量详解

    2024-07-16 00:02:05       24 阅读
  2. 力扣第六题——Z字形变换

    2024-07-16 00:02:05       20 阅读
  3. 数据结构初阶(C语言)-顺序表

    2024-07-16 00:02:05       22 阅读
  4. C# 做一个临时的对象结构,并用linq查找

    2024-07-16 00:02:05       16 阅读
  5. 动态路由-ospf

    2024-07-16 00:02:05       23 阅读
  6. 如何备份Syslog配置文件?

    2024-07-16 00:02:05       17 阅读
  7. float和double使用注意问题

    2024-07-16 00:02:05       19 阅读
  8. excel及panda的部分内容

    2024-07-16 00:02:05       20 阅读
  9. 消息中间件面试题

    2024-07-16 00:02:05       21 阅读