0-1背包问题-动态规划

    背包问题可以使用动态规划获得最优解,动态规划的思路是:通过获得单阶段的最优解后,升级到多阶段,每次升级时都使用上一阶段的最优解计算,避免遍历所有可能时产生的时间消耗。

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;
    }
}


猜你喜欢

转载自blog.51cto.com/zuohao1990/2322833