JAVA动态规划(五)--01背包问题及装箱问题
2016-04-22 22:07
447 查看
一、01背包问题:
问题:01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2……Wn,与之相对应的价值为P1,P2……Pn。在给定容量为C的条件下,求如何选取物体使带来的价值最大化。
在选择物品的时候,对每种物品i只有两种选择,即装入背包或不装入背包。不能讲物品i装入多次,也不能只装入物品的一部分。因此,该问题被称为0-1背包问题。
问题分析:令f(i,j)表示在前i(1<=i<=n)个物品中能够装入容量为j(1<=j<=C)的背包中的物品的最大价值,则可以得到如下的动态规划函数:
(1)V(i,0)=V(0,j)=0
(2)f(i,j)=f(i-1,j) j< wi ;
f(i,j)=max{f(i-1,j) ,f(i-1,j-wi)+vi) } j>wi
(1)式表明:如果第i个物品的重量大于背包的容量,则装人前i个物品得到的最大价值和装入前i-1个物品得到的最大价是相同的,即物品i不能装入背包;第(2)个式子表明:如果第i个物品的重量小于背包的容量,则会有一下两种情况:(a)如果把第i个物品装入背包,则背包物品的价值等于第i-1个物品装入容量位j-wi 的背包中的价值加上第i个物品的价值vi; (b)如果第i个物品没有装入背包,则背包中物品价值就等于把前i-1个物品装入容量为j的背包中所取得的价值。显然,取二者中价值最大的作为把前i个物品装入容量为j的背包中的最优解。
java代码如下:
二、装箱问题(一维):
问题: 装箱问题:有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积(正整数)。要求从m个物品中,任取若千个装入箱内,使箱子的剩余空间为最小。
分析:装箱问题与01背包问题差不多,状态转移方程也差不多。
f(i,j)表示前i件物品在给定j体积时所能达到的最大值。
f(i, j)=max(f(i-1,j) , f(i-1, j-vi)+vi)
代码:
问题:01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2……Wn,与之相对应的价值为P1,P2……Pn。在给定容量为C的条件下,求如何选取物体使带来的价值最大化。
在选择物品的时候,对每种物品i只有两种选择,即装入背包或不装入背包。不能讲物品i装入多次,也不能只装入物品的一部分。因此,该问题被称为0-1背包问题。
问题分析:令f(i,j)表示在前i(1<=i<=n)个物品中能够装入容量为j(1<=j<=C)的背包中的物品的最大价值,则可以得到如下的动态规划函数:
(1)V(i,0)=V(0,j)=0
(2)f(i,j)=f(i-1,j) j< wi ;
f(i,j)=max{f(i-1,j) ,f(i-1,j-wi)+vi) } j>wi
(1)式表明:如果第i个物品的重量大于背包的容量,则装人前i个物品得到的最大价值和装入前i-1个物品得到的最大价是相同的,即物品i不能装入背包;第(2)个式子表明:如果第i个物品的重量小于背包的容量,则会有一下两种情况:(a)如果把第i个物品装入背包,则背包物品的价值等于第i-1个物品装入容量位j-wi 的背包中的价值加上第i个物品的价值vi; (b)如果第i个物品没有装入背包,则背包中物品价值就等于把前i-1个物品装入容量为j的背包中所取得的价值。显然,取二者中价值最大的作为把前i个物品装入容量为j的背包中的最优解。
java代码如下:
package dynamic_programming; import java.util.Scanner; /** * @author Gavenyeah * * @date Time: 2016年4月22日下午5:41:02 */ //01背包问题,M件物品的重量不同,带来的价值不同,在给定最大重量容量下,找出能带来最大价值的组合 //状态转移方程: f(i,j)=max{f(i-1,j-wi)+vi, f(i-1,j)} public class Package_0_1 { int weight[]=null; int value[] = null; int C = 0; int m=0; public static void main(String[] args) { Package_0_1 p01 = new Package_0_1(); p01.getInput(); System.out.println(p01.getValue()); } public int getValue(){ int[][] maxValue=new int [m+1][C+1];//m和C的值加1的目的是避免单独处理i-0和j=0的情况 for(int i = 1; i < m+1; i++){ for(int j = 1; j < C + 1; j++){ if(j>=weight[i]) //根据状态转移方程计算当前最大价值 maxValue[i][j] = Math.max(maxValue[i-1][j-weight[i]]+value[i],maxValue[i-1][j]); else maxValue[i][j] = maxValue[i-1][j]; } } return maxValue[m][C];//返回m个物体,容量为C时的最大价值 } public void getInput() {//从键盘输入数据 Scanner cin = new Scanner(System.in); System.out.print("背包最大容量:"); C = cin.nextInt(); System.out.print("请输入物品数:"); m = cin.nextInt(); weight = new int[m+1]; System.out.print("依次输入每件物品的重量:"); for (int i = 1; i < m+1; i++) { weight[i] = cin.nextInt(); } System.out.print("依次输入每件物品的价值:"); value = new int[m+1]; for (int i = 1; i < m+1; i++) { value[i] = cin.nextInt(); } cin.close(); } }
二、装箱问题(一维):
问题: 装箱问题:有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积(正整数)。要求从m个物品中,任取若千个装入箱内,使箱子的剩余空间为最小。
分析:装箱问题与01背包问题差不多,状态转移方程也差不多。
f(i,j)表示前i件物品在给定j体积时所能达到的最大值。
f(i, j)=max(f(i-1,j) , f(i-1, j-vi)+vi)
代码:
package dynamic_programming; import java.util.Scanner; /** * @author Gavenyeah * @date Time: 2016年4月23日下午10:40:35 * @des: */ // 装箱问题:有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积 // (正整数)。要求从m个物品中,任取若千个装入箱内,使箱子的剩余空间为最小。 public class BinPacking { int volume[] = null; int max_V = 0; public static void main(String[] args) { BinPacking bp = new BinPacking(); bp.getInput(); bp.binPacking(); } // f(i,j)表示前i件物品在给定j体积时所能达到的最大值 public void binPacking() { int[][] maxSumVolume = new int[volume.length][max_V + 1]; for (int i = 1; i < volume.length; i++) { for (int j = 1; j <= max_V; j++) { if (j >= volume[i]) { maxSumVolume[i][j] = Math.max(maxSumVolume[i - 1][j], maxSumVolume[i - 1][j - volume[i]] + volume[i]); } } } int minSurplus = max_V - maxSumVolume[volume.length - 1][max_V]; System.out.println("最小剩余:" + minSurplus); } public void getInput() {// 从键盘输入数据 Scanner cin = new Scanner(System.in); System.out.print("请输入箱子容量:"); max_V = cin.nextInt(); System.out.print("请输入物品数:"); int m = cin.nextInt(); volume = new int[m + 1]; System.out.print("依次输入每件物品的重量:"); for (int i = 1; i < m + 1; i++) { volume[i] = cin.nextInt(); } cin.close(); } }
相关文章推荐
- Java IO学习
- JAVA动态规划(四)--根据给定0和1的个数,求字典序排在第K位的数【微软笔试题】
- LeetCode208 Implement Trie (Prefix Tree) Java
- java线程模型 线程池
- java毕向东听课笔记22(集合框架-List集合共性方法)
- JDK历史版本下载
- 第一节 Spring的环境搭建
- Java遍历容器注意问题
- 一些个人笔记(java第一季)
- JDK的动态代理
- (28)SpringBoot启动时的Banner设置【从零开始学Spring Boot】
- SSH中的exception is java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
- jdk中设计模式的实现
- JSON与JavaBean之间互转
- 欢迎使用CSDN-markdown编辑器
- 在myeclipse中添加反编译插件jad
- java 选择排序
- JAVA线程(一)
- Sturts2方法调用三种方式
- ubuntu 创建eclipse 快捷方式