(背包一)0-1背包问题

问题描述

小偷的背包容量是固定的W,物品重量wt[],对应的价值val[]。那么背包最大可以装多大的价值呢?

示例输入:
        int[] val = {48,40,12,8,7};
        int[] wt = {6,5,2,1,1};
        int W =8;
最大价值目测是48+8+7=63,容量刚好为6+1+1=8.那么对于复杂的输入,该如何写算法呢?

动态规划思路

二维数组dp[][], 行表示物体重量wt,列从底至顶0,1,2...W.

决策:放不放第i个物体呢?不放,则为i-1时的价值;放,则为i-1个物体在剩余容量下的价值+当前物体价值

公式:

(1) v[i][0]=v[0][j]=0;
(2) v[i][j]=Math.max(v[i-1][j],v[i-1][j-wt[i]]+val[i]); //(wt[i]<=j)
(3) v[i][j]=v[i-1][j]; //(wt[i]>j)

step1:初始化

weight \ capacity012345678
[0]->0–0––0––0––0––0––0––0––0––0–
[1]->6–0–
[2]->5–0–
[3]->2–0–
[4]->1–0–
[5]->1–0–

step1:从上到下从左到右依次填表

weight \ capacity012345678
[0]->0–0––0––0––0––0––0––0––0––0–
[1]->6–0–>
[2]->5–0–
[3]->2–0–
[4]->1–0–V[raw][col]
[5]->1–0–

代码

public class BeiBao01 {
    public static void main(String[] args) {

        //先定义出背包的一些数属性

        int[] val = {48,40,12,8,7};
        int[] wt = {6,5,2,1,1};
        int W =8;
        //int[] val = {10,40,30,50};
        //int[] wt = {5,4,6,3};
        //int W =12;

        int result = backpackage(val, wt, W);
        System.out.println(result);     
    }

    public static int backpackage(int[] val, int[] wt, int W){
        //1.获得物品(或价值)总数目
        int N = val.length;
        //2.建一个矩阵,行和列都多一行。0行0列都填充0
        /*     w
         *     0 1 2 3 4 5 6 7 8
         *n 0    
         *  1    * * * * * * * *
         *  2    *
         *  3    *
         *  4    *
         *  5    *
         */
        int[][] V = new int[N+1][W+1];
        //3.将0行0列都值为零
        for(int columns=0;columns<=W;columns++){
            V[0][columns]=0;
        }
        for(int row=0;row<=N;row++){
            V[row][0]=0;
        }
        //4.一行一行的填充,遍历二维数组即可

        for(int row = 1;row<=N;row++){
            for(int columns=1;columns<=W;columns++){
                //5.算法的精髓:矩阵怎么填充呢?
                //  V[i][j]=V[i-1][j]或者是V[i-1][j-当前重量]+当前价值   中的较大的那个
                if(wt[row-1]<=columns){    //单个重量比总容量小时。由于后边要做减法,做个判断(注意:等号不能忘)
                    V[row][columns]=Math.max(V[row-1][columns], 
                            V[row-1][columns-wt[row-1]]+val[row-1]);
                }else{
                    V[row][columns]=V[row-1][columns];
                }
            }
        }
        //6.选出最大值       
        //Printing the matrix
        /*
        for (int[] rows : V) {
            for (int col : rows) {
                System.out.format("%5d", col);
            }
            System.out.println();
        }        
        */
        int i=N;
        int j=W;
        while(i>0&&j>0){
            if(V[i][j]>V[i-1][j]){
                System.out.println("第"+i+"件物品,重"+wt[i-1]+",价值"+val[i-1]+"放入");
                j=j-wt[i-1];
                i--;
            }else{
                i--;
            }
        }


        return V[N][W];
    }
}

//结果5件物品,重1,价值7放入
第4件物品,重1,价值8放入
第1件物品,重6,价值48放入
63
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值