0-1揹包問題-動態規劃

    揹包問題能夠使用動態規劃得到最優解,動態規劃的思路是:經過得到單階段的最優解後,升級到多階段,每次升級時都使用上一階段的最優解計算,避免遍歷全部可能時產生的時間消耗。動態規劃解揹包問題時,須要藉助二維數組的表格。表格的行爲全部物品,表格的列爲步長遞增至揹包總容量,步長是優化二維數組表格的方法,取全部物品體積的最大公約數能夠使表格中的無用列最少。對應表格[行,列]的數據爲,當前物品列前(包括當前物品)的全部物品選擇放入揹包時的最大價值。每新計算一行時,須要判斷若是當前行的物品在揹包爲空的狀況下能夠放入時,剩餘空間能夠放的最大價值,這裏就須要參考上一行的數據,這也就是動態規劃的算法應用處。若是當前物品能夠放入且剩餘容量放入得到的最大價值加當前物品的最大價值大於上一行同一列的值時,更新當前列,不然使用上一行對應列的值填充。動態規劃最終創建的二維表格的數據會根據行的物品順序有所差別,可是最優解是同一個,就是二維表的最後一行的最好一列。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;
    }
}
相關文章
相關標籤/搜索