0-1揹包問題-動態規劃
阿新 • • 發佈:2018-11-27
揹包問題可以使用動態規劃獲得最優解,動態規劃的思路是:通過獲得單階段的最優解後,升級到多階段,每次升級時都使用上一階段的最優解計算,避免遍歷所有可能時產生的時間消耗。
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; } }