lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  1846 随笔 :: 0 文章 :: 109 评论 :: 288万 阅读

 

目录 

  • 01背包 二维写法
  • 01背包 一维写法
  • 完全背包 二维 带枚举写法
  • 完全背包 二维 普通写法
  • 完全背包 一维写法
  • 多重背包 二维写法
  • 多重背包 一维写法
  • 多重背包 一维写法二进制优化

 

1.  01背包 二维写法

  • dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1])
1
2
3
4
5
6
7
8
9
10
11
12
// 填写动态规划表
for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= C; j++) {
        if (j < w[i - 1]) {
            // 第i种物品的重量大于当前背包的剩余容量,不能放入
            dp[i][j] = dp[i - 1][j];
        } else {
            // 第i种物品的重量小于等于当前背包的剩余容量,可以选择放入或不放入
            dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]);
        }
    }
}

 

 

2.   01背包 一维写法

 

  • dp[j] = Math.max(dp[j], dp[j - w[i - 1]] + v[i - 1])  注:j逆序
1
2
3
4
5
6
7
for (int i = 1; i <= N; i++) {
    for (int j = C; j >= 0; j--) {
        if (j >= w[i - 1]) {
            dp[j] = Math.max(dp[j], dp[j - w[i - 1]] + v[i - 1]);
        }
    }
}

  

3.   完全背包 二维 带枚举写法

  • dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i - 1]] + k * w[i - 1])
1
2
3
4
5
6
7
8
9
// 状态转移
for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= V; j++) {
        dp[i][j] = dp[i - 1][j]; // 不装第i种物品
        for (int k = 0; k * v[i - 1] <= j; k++) { // 枚举装k个第i种物品
            dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i - 1]] + k * w[i - 1]); // 比较不装和装第i种物品的最大价值
        }
    }
}

  

4.  完全背包 二维 普通写法

  • dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - v[i - 1]] + w[i - 1])
1
2
3
4
5
for (int i = 1; i <= N; i++) {
    for (int j = v[i - 1]; j <= C; j++) {
        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - v[i - 1]] + w[i - 1]);
    }
}

  

1
<br><br> 

5.  完全背包 一维写法

  • dp[j] = Math.max(dp[j], dp[j - v[i - 1]] + w[i - 1])  注:j 顺序
1
2
3
4
5
   for (int i = 1; i <= N; i++) {
<strong>       for (int j = v[i - 1]; j <= C; j++) {</strong>
           dp[j] = Math.max(dp[j], dp[j - v[i - 1]] + w[i - 1]);
       }
   }

 

注意
这里的 dp[j] = Math.max(dp[j], dp[j - v[i - 1]] + w[i - 1])
实际是 dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - v[i - 1]] + w[i - 1]) 的简化,
这里用到了 dp[i][j - v[i - 1]],也就是说 计算当前层 不止用到了上一层,还用到了本层比较小的容量,这就是为什么必须正序的原因

6.   多重背包 二维写法

  • dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i]] + k * w[i])
1
2
3
4
5
6
7
for (int i = 1; i <= N; i++) { // 遍历物品
    for (int j = 0; j <= V; j++) { // 遍历背包容量
        for (int k = 0; k <= s[i] && k * v[i] <= j; k++) { // 遍历物品数量
            dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i]] + k * w[i]); // 状态转移
        }
    }
}

  

7.  多重背包 一维写法

  • dp[j] = Math.max(dp[j], dp[j - k * v[i - 1]] + k * w[i - 1])
1
2
3
4
5
6
7
for (int i = 1; i <= N; i++) {
    for (int j = C; j >= v[i - 1]; j--) {
        for (int k = 0; k <= s[i - 1] && k * v[i - 1] <= j; k++) {
            dp[j] = Math.max(dp[j], dp[j - k * v[i - 1]] + k * w[i - 1]);
        }
    }
}

  

 

8. 多重背包 一维写法二进制优化

  •  dp[j] = Math.max(dp[j], dp[j - k * v[i]] + k * w[i])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for (int i = 1; i <= N; i++) { // 遍历物品
    int k = 1; // 拆分因子
    while (k <= s[i]) { // 拆分数量不超过原数量
        for (int j = V; j >= k * v[i]; j--) { // 遍历背包容量
            dp[j] = Math.max(dp[j], dp[j - k * v[i]] + k * w[i]); // 状态转移
        }
        s[i] -= k; // 减去已拆分的数量
        k <<= 1; // 拆分因子翻倍
    }
    if (s[i] > 0) { // 如果还有剩余数量
        for (int j = V; j >= s[i] * v[i]; j--) { // 遍历背包容量
            dp[j] = Math.max(dp[j], dp[j - s[i] * v[i]] + s[i] * w[i]); // 状态转移
        }
    }
}

 

 

posted on   白露~  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2021-07-08 使用Guava RateLimiter限流以及源码解析
2021-07-08 方法论-索引
2021-07-08 神器 | 根因分析法,教你成为解决问题的高手
2021-07-08 java.util.Objects.isNull vs object == null 之Objects类的介绍
2021-07-08 好用的java.util.Objects类
2021-07-08 java.util.Objects 简介
2021-07-08 Java的对象工具类Objects
点击右上角即可分享
微信分享提示