0-1背包问题练习
来源:互联网 发布:航运货代 知乎 编辑:程序博客网 时间:2024/06/06 16:26
0-1背包问题练习
题目描述:
编号为a,b,c,d,e的5个物品,体积分别为2,2,6,5,4,价值分别为6,3,5,4,6。现在有一个容量为10的背包,如何往包中装东西,使得包里的物品总价值最大。
这就是0-1背包问题,0、1分别代表是否选在该物品。解决此类问题最常用的方法就是动态规划。
我们用一个数组记录背包容量从1到10的所有最优情况,只要能构造出这个数组,就能求出最优解。
需要说明的是,这张表是从下往上,从右往左填写的。对于e那行的第一列,我们用(e,1)表示,很明显(e,1)=0,(e,2)=0, (e,3)=0, (e, 4)=6 等等等等。
(e,1) = 0,表示当前只有e这一个物品,同时背包容量为1,由于e的体积大于背包容量,所以e放不进去,那么此时背包的最大价值是0。同理(e,4) = 6,表示背包容量为4时,e能放进去了,所以背包价值为6。
(d,1) = 0,表示当前物品有d和e,背包的容量为1,由于容量太小d和e都放不进去,所以背包的价值为0。同理(d,5) = 6,表示当背包容量为5时,d和e只能放一个,因为e的价值高,所以放入e,此时背包的价值为6。(d,9) = 10, 表示当背包容量为9时,d和e都能放进去,此时背包的价值是9。
经过上面的论述,可以总结出以下规律:
假设我们有0,1,2,…,i,…n个物体,用m(i, j)表示现在遍历到第 i 个物体,并且当前背包容量为 j 时背包的价值,
- 如果背包放不下它,那么m(i,j) = m(i-1, j),背包当前的状态和之前一样一样的
- 如果背包能放下它,那么m(i,j) = max{ m(i-1,j), m(i-1, j-c) + v) },放还是不放这是个问题,如果价值变大了,就放。其中c表示物体 i 的体积,v表示 i 的价值。
这个规律,就是传说中的状态转移方程~,有了它我们的程序就好写了。
注:程序没有考虑特殊输入,和非法输入,仅为了验证动态规划的思想。作者纯小白一枚~
import java.util.Arrays;/** * 0-1背包问题,用动态规划解决 * @author lijialin * */public class Bag { public static int solution(int[] cap, int[] val, int max_cap) { if(cap.length != val.length) { return -1; } // 首先建立dp矩阵 int num = cap.length; int[][] dp = new int[num][max_cap + 1]; // 从下往上填写dp矩阵,首先填写倒数第一行 for(int i = 0; i <= max_cap; i++) { if(i < cap[num-1]) { // 如果容量小于最后一个物品的体积 dp[num-1][i] = 0; }else { dp[num-1][i] = val[num-1]; } } // 然后从倒数第二行开始,用状态转移方程,依次填写表格 for(int i = num-2; i >= 0; i--) { for(int j = 0; j <= max_cap; j++) { if(j < cap[i]) { dp[i][j] = dp[i+1][j]; } else { dp[i][j] = Math.max(dp[i+1][j], dp[i+1][j - cap[i]] + val[i]); } } } // 打印表格 System.out.println("dp数组为:"); for(int i = 0; i < num; i++) { for(int j = 0; j <= max_cap; j++) { System.out.print(dp[i][j] + " "); } System.out.println(); } int max = dp[0][max_cap]; //背包的最大价值 // 构造出最优解 // 方法,从最后一列开始构造 int[] result = new int[num]; int i = 0; for(int j = max_cap; j >= 0 && i < num;) { if(i+1 < num && dp[i][j] == dp[i+1][j]) { result[i] = 0; }else{ result[i] = 1; j -= cap[i]; } i++; } // 打印result System.out.println("最优解是,0代表没选,1代表选了"); System.out.println(Arrays.toString(result)); return max; } public static void main(String[] args) { int[] cap = {2, 2, 6, 5, 4}; // 每个物品的体积 int[] val = {6, 3, 5, 4, 6}; // 每个物品的价值 int bag_cap = 10; //背包的总容量 int max_val = solution(cap, val, bag_cap); System.out.println(max_val); }}
总结一下:
理解状态转移方程,就理解了这个类型的问题
- 如果背包放不下它,那么m(i,j) = m(i-1, j),背包当前的状态和之前一样一样的
- 如果背包能放下它,那么m(i,j) = max{ m(i-1,j), m(i-1, j-c) + v) },放还是不放这是个问题,如果价值变大了,就放。其中c表示物体 i 的体积,v表示 i 的价值。
加油哦!!
- 0-1背包问题练习
- 编程练习:动态规划0-1背包问题
- 算法练习-背包问题
- 背包问题(0-1背包、完全背包、多重背包)详解
- 背包问题练习之邮票
- 背包问题和0-1背包问题
- 背包问题和0-1背包问题
- 背包问题系列--"0-1背包问题"
- 简单背包练习——0/1背包
- 背包笔记-含0/1背包问题、完全背包问题、多重背包问题、二维背包问题、分组背包问题
- 程序设计实习动态规划练习 Charm Bracelet(0/1背包问题dp)
- 【背包问题】背包问题之0-1背包、完全背包、多重背包
- 0-1背包问题
- 0/1背包问题
- 0,1背包问题
- 0-1背包问题
- 0/1背包问题
- 0-1背包问题
- [Leetcode] 343. Integer Break 解题报告
- ORACLE EBS :Oracle.apps.fnd.cp.request 并发常用JAVA方法
- svn 服务器端和客户端配置方法
- Monthly Expense(二分法)
- python uiautomator API
- 0-1背包问题练习
- SpringCloud分布式开发五大神兽
- [LeetCode]237. Delete Node in a Linked List
- @SpringBootApplication注解
- echarts ajax请求方式
- wp-postviews文章浏览次数与点击排行详解
- msiexec.exe进程在安装sqlserver 2012 sp1后继续运行,增加到约100%CPU
- Leetcode 442. Find All Duplicates in an Array
- 关于js模糊匹配