背包九讲(超值得看的一大坨资料,附代码、视频、资料...)
背包九讲概述
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
总结
一句话先循环物品再循环体积再循环决策
背包九讲(超值得看的一大坨资料,附代码、视频、资料...)相关推荐
- 【算法】动态规划+“背包九讲”原理超详细讲解+常见dp问题(9种)总结
目录 一.动态规划(DP) 二.背包九讲 (1)完全背包 P1616 疯狂的采药(完全背包) (2)01背包 滚动数组 一维数组 P1048 采药(01背包) 01背包表格图示 (3)多重背包 整数拆 ...
- 算法--背包九讲(详细讲解+代码)
背包九讲 目录 第一讲 01背包问题 第二讲 完全背包问题 第三讲 多重背包问题 第四讲 混合三种背包问题 第五讲 二维费用的背包问题 第六讲 分组的背包问题 第七讲 有依赖的背包问题 ...
- dalao的背包九讲
背包九讲 目录 第一讲 01背包问题 第二讲 完全背包问题 第三讲 多重背包问题 第四讲 混合三种背包问题 第五讲 二维费用的背包问题 第六讲 分组的背包问题 第七讲 有依赖的背包问题 ...
- 【转】《背包九讲》--崔添翼大神
背包九讲 目录 第一讲 01背包问题 第二讲 完全背包问题 第三讲 多重背包问题 第四讲 混合三种背包问题 第五讲 二维费用的背包问题 第六讲 分组的背包问题 第七讲 有依赖的背包问题 第八讲 泛化物 ...
- 转载——背包九讲(原文链接已不可考)
浙大崔添翼对背包问题的讲解,观点很高也很深刻,特此转载. 背包九讲 目录 第一讲 01背包问题 第二讲 完全背包问题 第三讲 多重背包问题 第四讲 混合三种背包问题 第五讲 二维费用的背包问 ...
- Backpack-problem背包九讲笔记
背包问题 1 01背包 1.1题目 有NNN件物品和一个容量为VVV的背包,放入第iii件物品耗费的费用是CiC_iCi,得到的价值是WiW_iWi.求解将哪些物品放入背包可使价值总和最大. ex ...
- dd大牛的背包九讲-背包问题汇总
背包九讲 目录 第一讲 01背包问题 第二讲 完全背包问题 第三讲 多重背包问题 第四讲 混合三种背包问题 第五讲 二维费用的背包问题 第六讲 分组的背包问题 第七讲 有依赖的背包问题 ...
- 背包九讲 (蒟蒻版)之01背包
hello,你们的loony上线啦.你们知道吗?我今天早上起来一看手机,600多人在CSDN上访问过我,当时我心情都要炸了(补充:高兴炸了),因为,这毕竟只是本蒟蒻的梦想嘛~ 好了不嘚瑟啦! 今天就来 ...
- dp背包九讲(待补充,暂时前两讲)
文章目录 背包九讲 一.01背包 二维dp 优化为一维 二.完全背包 二维dp 优化为一维 三.多重背包 数据范围很小时,变成01背包暴力 当数据范围较大时,利用二进制优化 二进制优化还不够用时,利用 ...
- 第二讲 完全背包问题(对背包九讲的学习)
学习自:背包九讲 题目 有N种物品和一个容量为V的背包,每种物品都有无限件可用.第i种物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. ...
最新文章
- NVIDIA CUDA-X AI
- 使用WebBrowser与msHtml开发WinForms下的HtmlEditor控件
- 为什么使用Maven
- 使用docker搭建FastDFS文件系统
- 点云3D目标检测学习(3):Complex YOLO
- 前端取消置顶功能_双十一来临,怎么让便签app记录的清空购物车便签内容置顶显示? - 学显...
- 报表如何同步用户数据集 1
- 三阶段提交(Three-phase commit)
- Android模拟器读取GPS串口模拟器GPS数据
- 算法探究:线性时间选择问题
- 二年级上册计算题_小学二年级上册应用题500道
- 定时任务task:annotation-driven配置
- DZS与EPS Global合作,加速下一代接入基础设施在欧洲和亚洲的应用
- 100天精通Python丨基础知识篇 —— 02、Python和Pycharm(语言特点、学习方法、工具安装)
- 使用一键重装系统后,如何删除多余的PE系统引导菜单?
- 【解决方案 十二】一文彻底解决文件格式判别问题
- js递归返回想要的值
- 你误把饥渴当成了爱情
- 如何安装IBM QISKit
- 05.Shell字符串处理