0-1背包动态规划,获取最优选择和最优解

package com.example.demo.paixu;

import java.util.Scanner;

/**
 * @Description TODO
 * @Date 2020/4/19 16:10
 * @Created by zengq
 */
public class Dp {

    public static void main(String[] args) {
        //第0个物品的重量和价值都为0
        int[] weights = {0,2,3,4,5};
        int[] values = {0,3,4,5,6};
        while (true){
            Scanner sc = new Scanner(System.in);
            int item = sc.nextInt();
            int volume = sc.nextInt();
            int[][] dp = createDp(weights, values, item, volume);
            /*for (int i = 0; i < dp.length; i++) {
                for (int j = 0; j < dp[i].length; j++) {
                    System.out.print(dp[i][j] + " ");
                }
                System.out.println("---------------------");
            }*/
            System.out.println(dp[item][volume]);
        }

    }

    /**
     * 背包问题dp数组的构建思路
     * 1、不可以放入背包:当前物品重量大于背包容量,无法放入背包,dp[i,j]=dp[i-1,j]
     * 2、可以放入背包:当前物品重量小于等于背包容量,可以放入背包
     *      1、不放入背包时最大价值为dp[i,j]=dp[i-1,j]
     *      2、放入背包时的最大价值为dp[i,j]=dp[i-1,j-weights[i]]+values[i]
     *    选取放入和不放入中价值较大者作为dp[i,j]的最大价值
     * @param weights   重量
     * @param values    价值
     * @param item      总共有多少个物品
     * @param volume    背包总容纳量
     * @return
     */
    public static int[][] createDp(int[] weights, int[] values, int item, int volume){
        //dp[i,j]表示背包总容纳量为j时前i个物品可选出的最大价值
        int[][] dp = new int[item+1][volume+1];
        //记录放进背包的索引链
        String[][] index = new String[item+1][volume+1];
        //i=0跟j=0是,对应值全为0,默认值也是0,不用主动赋值
        for (int i = 1; i <= item; i++) {
            for (int j = 1; j <= volume; j++) {
                if(weights[i] > j) {
                    //无法放入背包
                    dp[i][j] = dp[i-1][j];
                    index[i][j] = index[i-1][j];
                }else {
                    //放入背包和不放入背包中较大者
                    /*dp[i][j] = dp[i-1][j] > (dp[i-1][j-weights[i]] + values[i]) ? dp[i-1][j] :(dp[i-1][j-weights[i]] + values[i]);*/
                    if (dp[i-1][j] > (dp[i-1][j-weights[i]] + values[i])){
                        //不放进去
                        dp[i][j] = dp[i-1][j];
                        index[i][j] = index[i-1][j];

                    }else if (dp[i-1][j] <= (dp[i-1][j-weights[i]] + values[i])){
                        //放进去
                        dp[i][j] = dp[i-1][j-weights[i]] + values[i];
                        index[i][j] = index[i-1][j-weights[i]] + "-" + i;

                        //相等的话可以放进去也可以不放进去,总价值不变,选择的物品可能有所不同,需要注意,如上只考虑相等就放进去这种方式
                    }
                }
            }
        }
        System.out.println("选择物品为:" + index[item][volume].substring(5));
        return  dp;
    }
}

你可能感兴趣的:(面试题或算法)