背包九讲概述

1. 01背包问题

题目

  • 01背包问题

每件物品只能选0次或者1次

2. 完全背包问题

题目

  • 完全背包问题

每件物品可以选无数次

3. 多重背包问题

题目

  • 多重背包问题 I

限定每件物品的数量

4. 混合背包问题

题目

  • 混合背包问题

有的物品只能选一次,有的可以选无限次,有的可以选n次

5. 二维费用的背包问题

题目

  • 二维费用的背包问题

物品拥有体积质量和价值

6. 分组背包问题

题目

  • 分组背包问题

若干组物品,每一组只能选一个

7. 背包问题求方案数

题目

  • 背包问题求方案数

最优解的数量

8. 求背包问题的方案

题目

  • 背包问题求具体方案

输出最优方案

9. 有依赖的背包问题

如果选择某个物品,就必须先选择他的父节点物品

10、用最少的物品填满背包

题目

  • 322. 零钱兑换

用最少的物品填满背包

1、01背包

动态规划DP0-1背包

理解

思路

首先要理解:
f(k,w):当背包容量为w,现有k件物品可以偷,所能偷盗的最大价值

01背包是后面八种背包的基础,搞清楚01背包后面八种背包一看就会!!!!

谨记一句话:一句话先循环物品再循环体积再循环决策


代码实现

代码


package com.review.backpack_01;public class BP01 {//01背包问题//每件物品只能选0次或者1次private int maxValue(int[] weight, int[] value, int bagWeight) {//常规做法// dp[i][j]的含义是:可选物品为i,背包容量是j时背包的最大价值// new int[weight.length][bagWeight + 1]为什么是bagWeight + 1呢?// 因为j代表的背包的真实容量,但是数组是从0开始的int[][] dp = new int[weight.length][bagWeight + 1];// 因为dp[0][j]中的0对应的是第一件物品,所以dp[0][j]的含义是可选物品为1,背包容量为j;// 当j大于等于weight[0]此时背包最大价值就是value[0]也就是第一件物品的价值for (int j = bagWeight; j >= weight[0]; j--) {dp[0][j] = value[0];}for (int i = 1; i < dp.length; i++) {for (int j = 1; j < dp[0].length; j++) {if (j < weight[i]) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);}}}return dp[dp.length - 1][dp[0].length - 1];}private int maxValue2(int[] weight, int[] value, int bagWeight) {//改进做法,使用一维数组int[] dp = new int[bagWeight + 1];for (int i = 0; i < weight.length; i++) {for (int j = bagWeight; j >= weight[i]; j--) {dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);}}return dp[dp.length - 1];}public static void main(String[] args) {System.out.println("常规做法,使用二维数组:" + new BP01().maxValue(new int[]{1, 3, 4}, new int[]{15, 20, 30}, 4));System.out.println("改进做法,使用一维数组:" + new BP01().maxValue2(new int[]{1, 3, 4}, new int[]{15, 20, 30}, 4));}
}

运行结果

常规做法,使用二维数组:35
改进做法,使用一维数组:35Process finished with exit code 0

2、完全背包

代码实现

package com.review.backpack_01;public class BP02 {//2. 完全背包问题//每件物品可以选无数次private int maxValue(int[] weight, int[] value, int bagWeight) {//改进做法int[] dp = new int[bagWeight + 1];for (int i = 0; i < weight.length; i++) {for (int j = weight[i]; j <= bagWeight; j++) {dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);}}return dp[dp.length - 1];}private int maxValue2(int[] weight, int[] value, int bagWeight) {//常规做法int[] dp = new int[bagWeight + 1];for (int i = 0; i < weight.length; i++) {for (int j = bagWeight; j >= weight[i]; j--) {for (int k = 0; k * weight[i] <= j; k++) {dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);}}}return dp[dp.length - 1];}public static void main(String[] args) {System.out.println("常规做法:" + new BP02().maxValue2(new int[]{1, 3, 4}, new int[]{15, 20, 30}, 4));System.out.println("改进做法:" + new BP02().maxValue(new int[]{1, 3, 4}, new int[]{15, 20, 30}, 4));}
}

运行结果

常规做法:60
改进做法:60Process finished with exit code 0

3、多重背包

代码实现

package com.review.backpack_01;public class BP03 {//3. 多重背包问题//限定每件物品的数量private int maxValue(int[] weight, int[] value, int[] num, int bagWeight) {int[] dp = new int[bagWeight + 1];for (int i = 0; i < weight.length; i++) {for (int j = bagWeight; j >= weight[i]; j--) {//前半部分和01背包相同for (int k = 1; k <= num[i] && k * weight[i] <= j; k++) {dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);}}}return dp[dp.length - 1];}//优化private int maxValue2(int[] weight, int[] value, int[] num, int bagWeight) {int[] dp = new int[bagWeight + 1];for (int i = 0; i < weight.length; i++) {int s = num[i];for (int j = 1; j <= s; s -= j, j <<= 1) {for (int k = bagWeight; k >= 0 && k >= weight[i] * j; k--) {dp[k] = Math.max(dp[k], dp[k - j * weight[i]] + j * value[i]);}}if (s > 0) {for (int j = bagWeight; j >= s * weight[i]; j--) {dp[j] = Math.max(dp[j], dp[j - s * weight[i]] + s * value[i]);}}}return dp[dp.length - 1];}public static void main(String[] args) {System.out.println(new BP03().maxValue(new int[]{1, 2, 3, 4}, new int[]{2, 4, 4, 5}, new int[]{3, 1, 3, 2}, 5));//10System.out.println(new BP03().maxValue2(new int[]{1, 2, 3, 4}, new int[]{2, 4, 4, 5}, new int[]{3, 1, 3, 2}, 5));//10}
}

运行结果

10
10Process finished with exit code 0

4、混合背包

代码实现

package com.some;import com.review.backpack_01.BP04;public class BP04_test {/*混合背包p=−1  表示第 i 种物品只能用1次;p=0 表示第 i 种物品可以用无限次;p>0 表示第 i 种物品可以使用 p 次;*/public static int knapsackProblem(int[] w, int[] v, int[] p, int cap) {int[] dp = new int[cap + 1];for (int i = 0; i < w.length; i++) {if (p[i] == -1) {// 01背包for (int j = cap; j >= w[i]; j--) {dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]);}} else if (p[i] == 0) {// 完全背包for (int j = w[i]; j <= cap; j++) {dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]);}} else {// 多重背包for (int j = cap; j >= w[i]; j--) {for (int k = 0; (k <= p[i]) && (k * w[i] <= j); k++) {dp[j] = Math.max(dp[j], dp[j - k * w[i]] + k * v[i]);}}}}return dp[cap];}public static void main(String[] args) {System.out.println(knapsackProblem(new int[]{2, 3, 4, 5, 6, 7, 8},new int[]{3, 4, 5, 6, 7, 8, 9},new int[]{1, 1, 0, 0, 1, 3, 4}, 27));System.out.println(knapsackProblem(new int[]{1, 2, 3, 4},new int[]{2, 4, 4, 5},new int[]{-1, 1, 0, 2}, 5));}
}

运行结果

34
8Process finished with exit code 0

5、二维费用的背包问题

代码实现

package com.review.backpack_01;public class BP05 {//5. 二维费用的背包问题//物品拥有体积质量和价值public int knapsackProblem(int[] volume, int maxV, int[] weight, int maxW, int[] value) {int[][] dp = new int[maxV + 1][maxW + 1];for (int i = 0; i < volume.length; i++) {for (int j = maxV; j >= volume[i]; j--) {for (int k = maxW; k >= weight[i]; k--) {dp[j][k] = Math.max(dp[j][k], dp[j - volume[i]][k - weight[i]] + value[i]);}}}return dp[maxV][maxW];}public static void main(String[] args) {System.out.println(new BP05().knapsackProblem(new int[]{1, 2, 3, 4},5,new int[]{2, 4, 4, 5},6,new int[]{3, 4, 5, 6}));}
}

运行结果

8Process finished with exit code 0

6、 分组背包问题

代码实现

package com.review.backpack_01;public class BP06 {//6. 分组背包问题//若干组物品,每一组只能选一个public int knapsackProblem(int[][] c, int[][] v, int cap) {int[] dp = new int[cap + 1];for (int i = 0; i < c.length; i++) {for (int j = cap; j >= 0; j--) {// 确保每个组中至多只有一个物品被选择for (int k = 0; k < c[i].length; k++) {if (j >= c[i][k]) {dp[j] = Math.max(dp[j], dp[j - c[i][k]] + v[i][k]);}}}}return dp[cap];}public static void main(String[] args) {System.out.println(new BP06().knapsackProblem(new int[][]{{1, 2, 3}, {2, 3, 4}, {5, 6, 7, 8}, {7, 9}},new int[][]{{2, 3, 4}, {1, 2, 3}, {4, 5, 6, 7}, {8, 9}},11));}
}

运行结果

12Process finished with exit code 0

7、背包问题求方案数

  • AcWing 11. Java-背包问题求方案数—注释版代码

代码实现

package com.review.backpack_01;import java.util.Arrays;public class BP07_2 {//7. 背包问题求方案数//最优解的数量//在01背包里加入判断public static int knapsackProblem(int[] c, int[] v, int V) {int[] dp = new int[V + 1];int[] count = new int[V + 1];// 初始化,此时的count代表i=0,即没有物品可以选择时// 什么都不选,也是一种方案Arrays.fill(count, 1);for (int i = 0; i < c.length; i++) {for (int j = V; j >= c[i]; j--) {if (dp[j] < dp[j - c[i]] + v[i]) {// 选择当前物品的收益要高,因此这里dp的选择必然是选择当前物品,// 因为是必然,所以这样的方案数量不变count[j] = count[j - c[i]];} else if (dp[j] == dp[j - c[i]] + v[i]) {// 二者的收益相等,这里可以选,也可以不选// 因此这里是加上count[j-v[i]]count[j] += count[j - c[i]];} else {// 不选的收益更高,那么这里dp的选择必然是不选// 因此保持count[n-1][j]即可}dp[j] = Math.max(dp[j], dp[j - c[i]] + v[i]);}}return count[V];}public static int knapsackProblem_2(int[] c, int[] v, int V) {int[][] dp = new int[c.length + 1][V + 1];int[][] count = new int[c.length + 1][V + 1];// 初始化,此时的count代表i=0,即没有物品可以选择时// 什么都不选,也是一种方案for (int[] ints : count) {Arrays.fill(ints, 1);}for (int i = 1; i < c.length; i++) {for (int j = 0; j <= V; j++) {if (j >= c[i]) {// 背包容量大于当前物品容量if (dp[i - 1][j] < dp[i - 1][j - c[i]] + v[i]) {// 选择当前物品的收益更高// 更新当前收益dp[i][j] = dp[i - 1][j - c[i]] + v[i];// 当前方案只是在之前方案的基础上加了当前的物品,因此方案数量不变count[i][j] = count[i - 1][j - c[i]];} else if (dp[i - 1][j] == dp[i - 1][j - c[i]] + v[i]) {// 两种办法收益相等// 更新当前收益dp[i][j] = dp[i - 1][j];// 当前方案有两种选择,一是不增加当前物品,二是增加当前物品,所以方案数量等于二者之和count[i][j] = count[i - 1][j] + count[i - 1][j - c[i]];} else {// 选择当前物品的收益更高// 更新当前收益dp[i][j] = dp[i - 1][j];// 当前方案不增加物品,与之前的方案等同count[i][j] = count[i - 1][j];}} else {// 背包容量下雨当前物品容量dp[i][j] = dp[i - 1][j];count[i][j] = count[i - 1][j];}}}return count[c.length][V];}public static void main(String[] args) {System.out.println(knapsackProblem(new int[]{1, 3, 4}, new int[]{15, 20, 30}, 4));System.out.println(knapsackProblem_2(new int[]{1, 3, 4}, new int[]{15, 20, 30}, 4));}
}

运行结果

1
1Process finished with exit code 0

8、求背包问题的方案

代码实现

package com.review.backpack_01;import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;public class BP08_2 {//8. 求背包问题的方案//输出最优方案public static int knapsackProblem(int[] c, int[] v, int cap) {// 记录最大价值int[][] dp = new int[c.length][cap + 1];// 记录当前物品是否被选择int[][] choose = new int[c.length][cap + 1];for (int i = cap; i >= c[0]; i--) {dp[0][i] = v[0];choose[0][i] = 1;}for (int i = 1; i < c.length; i++) {for (int j = 1; j <= cap; j++) {if (j >= c[i]) {if (dp[i - 1][j] <= dp[i - 1][j - c[i]] + v[i]) {// 选择当前物品为最优解dp[i][j] = dp[i - 1][j - c[i]] + v[i];choose[i][j] = 1;} else {dp[i][j] = dp[i - 1][j];}} else {dp[i][j] = dp[i - 1][j];}}}// 反推出物品编号List<Integer> list = new LinkedList<>();int i = c.length - 1, V = cap;while (i >= 0) {if (choose[i][V] != 0) {list.add(i);V -= c[i];}i--;}Collections.reverse(list);System.out.println("最优方案选择:" + list);return dp[dp.length - 1][dp[0].length - 1];}public static void main(String[] args) {System.out.println(knapsackProblem(new int[]{1, 3, 4}, new int[]{15, 20, 30}, 4));}
}

运行结果

最优方案选择:[0, 1]
35Process finished with exit code 0

10、用最少的物品填满背包

代码实现

import java.util.Arrays;public class BP10 {public static int coinChange(int[] coins, int amount) {int[] dp = new int[amount + 1];Arrays.fill(dp, amount + 1);dp[0] = 0;for (int i = 0; i < coins.length; i++) {for (int j = coins[i]; j <= amount; j++) {dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);}}return dp[amount] == (amount + 1) ? -1 : dp[amount];}public static void main(String[] args) {System.out.println(coinChange(new int[]{1, 2, 5}, 11));}
}

运行结果

3Process finished with exit code 0

资料引用

视频链接(B站)

https://www.bilibili.com/video/BV1qt411Z7nE?from=search&seid=1595971988062633820

https://www.bilibili.com/video/av34467850/?p=2&spm_id_from=333.788.b_636f6d6d656e74.18

题库链接

https://www.acwing.com/problem/

优秀博客(借鉴)

https://blog.csdn.net/qq_14873461/category_9800545.html

网上资料

背包问题九讲

https://ishare.iask.sina.com.cn/f/17570695.html

背包九讲 2.0.pdf

https://max.book118.com/html/2017/0615/115637327.shtm

代码

码云

https://gitee.com/huangjialin3344/leet-code-test/tree/master/LeetCode_time_1022/src/main/java/com/review/backpack_01

总结

一句话先循环物品再循环体积再循环决策

背包九讲(超值得看的一大坨资料,附代码、视频、资料...)相关推荐

  1. 【算法】动态规划+“背包九讲”原理超详细讲解+常见dp问题(9种)总结

    目录 一.动态规划(DP) 二.背包九讲 (1)完全背包 P1616 疯狂的采药(完全背包) (2)01背包 滚动数组 一维数组 P1048 采药(01背包) 01背包表格图示 (3)多重背包 整数拆 ...

  2. 算法--背包九讲(详细讲解+代码)

    背包九讲 目录  第一讲 01背包问题  第二讲 完全背包问题  第三讲 多重背包问题  第四讲 混合三种背包问题  第五讲 二维费用的背包问题  第六讲 分组的背包问题  第七讲 有依赖的背包问题  ...

  3. dalao的背包九讲

    背包九讲 目录  第一讲 01背包问题  第二讲 完全背包问题  第三讲 多重背包问题  第四讲 混合三种背包问题  第五讲 二维费用的背包问题  第六讲 分组的背包问题  第七讲 有依赖的背包问题  ...

  4. 【转】《背包九讲》--崔添翼大神

    背包九讲 目录 第一讲 01背包问题 第二讲 完全背包问题 第三讲 多重背包问题 第四讲 混合三种背包问题 第五讲 二维费用的背包问题 第六讲 分组的背包问题 第七讲 有依赖的背包问题 第八讲 泛化物 ...

  5. 转载——背包九讲(原文链接已不可考)

    浙大崔添翼对背包问题的讲解,观点很高也很深刻,特此转载. 背包九讲 目录  第一讲 01背包问题  第二讲 完全背包问题  第三讲 多重背包问题  第四讲 混合三种背包问题  第五讲 二维费用的背包问 ...

  6. Backpack-problem背包九讲笔记

    背包问题 1 01背包 1.1题目 有NNN件物品和一个容量为VVV的背包,放入第iii件物品耗费的费用是CiC_iCi​,得到的价值是WiW_iWi​.求解将哪些物品放入背包可使价值总和最大. ex ...

  7. dd大牛的背包九讲-背包问题汇总

    背包九讲 目录  第一讲 01背包问题  第二讲 完全背包问题  第三讲 多重背包问题  第四讲 混合三种背包问题  第五讲 二维费用的背包问题  第六讲 分组的背包问题  第七讲 有依赖的背包问题  ...

  8. 背包九讲 (蒟蒻版)之01背包

    hello,你们的loony上线啦.你们知道吗?我今天早上起来一看手机,600多人在CSDN上访问过我,当时我心情都要炸了(补充:高兴炸了),因为,这毕竟只是本蒟蒻的梦想嘛~ 好了不嘚瑟啦! 今天就来 ...

  9. dp背包九讲(待补充,暂时前两讲)

    文章目录 背包九讲 一.01背包 二维dp 优化为一维 二.完全背包 二维dp 优化为一维 三.多重背包 数据范围很小时,变成01背包暴力 当数据范围较大时,利用二进制优化 二进制优化还不够用时,利用 ...

  10. 第二讲 完全背包问题(对背包九讲的学习)

    学习自:背包九讲 题目 有N种物品和一个容量为V的背包,每种物品都有无限件可用.第i种物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. ...

最新文章

  1. NVIDIA CUDA-X AI
  2. 使用WebBrowser与msHtml开发WinForms下的HtmlEditor控件
  3. 为什么使用Maven
  4. 使用docker搭建FastDFS文件系统
  5. 点云3D目标检测学习(3):Complex YOLO
  6. 前端取消置顶功能_双十一来临,怎么让便签app记录的清空购物车便签内容置顶显示? - 学显...
  7. 报表如何同步用户数据集 1
  8. 三阶段提交(Three-phase commit)
  9. Android模拟器读取GPS串口模拟器GPS数据
  10. 算法探究:线性时间选择问题
  11. 二年级上册计算题_小学二年级上册应用题500道
  12. 定时任务task:annotation-driven配置
  13. DZS与EPS Global合作,加速下一代接入基础设施在欧洲和亚洲的应用
  14. 100天精通Python丨基础知识篇 —— 02、Python和Pycharm(语言特点、学习方法、工具安装)
  15. 使用一键重装系统后,如何删除多余的PE系统引导菜单?
  16. 【解决方案 十二】一文彻底解决文件格式判别问题
  17. js递归返回想要的值
  18. 你误把饥渴当成了爱情
  19. 如何安装IBM QISKit
  20. 05.Shell字符串处理

热门文章

  1. sha1算法源码c版
  2. PHP四合一小说漫画听书视频网站源码 带采集
  3. 推美妆、搭IP,出货千万的天猫精灵打上95后的主意...
  4. turtle画动态时钟
  5. 海康威视设备发现sdp原理
  6. 不使用中国手机号码注册网易云音乐
  7. Javascript学习
  8. LinuxCNC的能做什么
  9. Sql Server 数据库实验报告
  10. 疯狂程序员网址。。。