背包问题能够使用动态规划得到最优解,动态规划的思路是:经过得到单阶段的最优解后,升级到多阶段,每次升级时都使用上一阶段的最优解计算,避免遍历全部可能时产生的时间消耗。动态规划解背包问题时,须要借助二维数组的表格。表格的行为全部物品,表格的列为步长递增至背包总容量,步长是优化二维数组表格的方法,取全部物品体积的最大公约数能够使表格中的无用列最少。对应表格[行,列]的数据为,当前物品列前(包括当前物品)的全部物品选择放入背包时的最大价值。每新计算一行时,须要判断若是当前行的物品在背包为空的状况下能够放入时,剩余空间能够放的最大价值,这里就须要参考上一行的数据,这也就是动态规划的算法应用处。若是当前物品能够放入且剩余容量放入得到的最大价值加当前物品的最大价值大于上一行同一列的值时,更新当前列,不然使用上一行对应列的值填充。动态规划最终创建的二维表格的数据会根据行的物品顺序有所差别,可是最优解是同一个,就是二维表的最后一行的最好一列。java
package test; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * Created by saishangmingzhu on 2018/11/27. */ public class Rucksack { //【1】输入背包容量 //【2】输入物品体积及价值 public static void main(String[] arg) { new Rucksack().dynamic(); } /** * 动态规划 【1】定义表格,物品体积的最大公约数做为列的步长求出最短列,物品做为行 【2】定义物品,名称、体积、价值 */ public void dynamic(){ int rucksackV=10; List<Goods> goodsList=new ArrayList<>(); int i=0; goodsList.add(i++,new Goods("0",0,0));//方便构建表格使用,无业务意义 //测试最大公约数为1的状况 goodsList.add(i++,new Goods("书",1,2)); goodsList.add(i++,new Goods("足球",3,4)); goodsList.add(i++,new Goods("大箱子",7,2)); goodsList.add(i++,new Goods("macbook",3,6)); goodsList.add(i++,new Goods("iphone",1,5)); goodsList.add(i++,new Goods("礼盒",5,3)); goodsList.add(i++,new Goods("小箱子",4,2)); // //测试最大公约数为2的状况 // goodsList.add(i++,new Goods("书",2,2)); // goodsList.add(i++,new Goods("足球",4,4)); // goodsList.add(i++,new Goods("大箱子",8,2)); // goodsList.add(i++,new Goods("macbook",6,6)); int step=getGCD(goodsList,rucksackV); //表格中第0行,第0列无业务意义,使用的意义是不须要在后续表格使用中判断坐标越界,用空间换时间 int colum=rucksackV/step+1; int[][] table=new int[i][colum]; for (int m=1;m<goodsList.size();m++){ Goods goods=goodsList.get(m); for (int n=1;n<colum;n++){ //确保当前物品单独能够放入背包 table[m][n]=table[m-1][n]; int surplus=n*step-goods.getVolume(); if (surplus>=0){ int worth=goods.getWorth()+table[m-1][surplus/step]; if (worth>table[m-1][n]){ table[m][n]=worth; } } } } for (int m=1;m<table.length;m++){ for (int n=1;n<table[m].length;n++){ if (table[m][n]<10) System.out.print(" "+table[m][n]+","); else System.out.print(table[m][n]+","); } System.out.println(); } } /** * 求解最大公约数 * @param goodsList * @param rucksackV * @return */ public int getGCD(List<Goods> goodsList,int rucksackV){ int minV=rucksackV; int[] vs=new int[goodsList.size()-1];//-1为去除没有业务意义的第一个 for (int i=0;i<goodsList.size()-1;i++){ vs[i]=goodsList.get(i+1).getVolume(); if (vs[i]<minV){ minV=vs[i]; } } boolean flag=true; while (minV>1){ for (int v:vs){ if(v%minV!=0){ flag=false; break; } } if (flag){ break; } minV--; } return minV; } } class Goods{ private String name; private int volume; private int worth; public Goods(){} public Goods(String n,int v,int w){ this.name=n; this.volume=v; this.worth=w; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getVolume() { return volume; } public void setVolume(int volume) { this.volume = volume; } public int getWorth() { return worth; } public void setWorth(int worth) { this.worth = worth; } }