背包问题

来源:互联网 发布:张逗张花 知乎 编辑:程序博客网 时间:2024/06/10 06:19
public class Solution {    public static void main(String[] args) {        int[] weight = {2, 3, 5, 4};    // 物品重量数组        int[] value = {3, 4, 5, 6};     // 物品价值数组        int capacity = 13;              // 背包容量                     int num = value.length;         // 物品数目        System.out.println("背包最大价值: " + Solution.backPack(capacity, num, weight, value));    }    /**     * 0-1背包问题——动态规划     *      * 思路分析:     *  1. 构造两个动态规划用到的数组     *      maxValue[][]——"物品-容量-价值"数组      path[][]——"放入位置"数组     *      maxValue[i-1][j]——表示前i个物品装入容量为j的背包中的最大价值     *      maxValue[i-1][j-w[i]]——前i个物体放入容量为j-w[i]的背包的最大价值     *      *  2. 对于放入背包中的第i件物品:     *      若第i件物品重量小于等于背包容量,则可以放入     *          若第i件物品放入后背包总价值变大,则修改maxValue[][]和path[][]数组     *          否则背包总价值不变     *      *      否则无法放入,背包价值不变     *      * @param c: 背包容量     * @param n: 物品数目     * @param w: w[i-1]——第i个物品的重量     * @param v: v[i-1]——第i个物品的价值     * @return     */    public static int backPack(int c, int n, int[] w, int[] v) {    // 动态规划用到的"物品-容量-价值"数组        int[][] maxValue = new int[n+1][c+1];    // 动态规划"路径"数组        int[][] path = new int[n+1][c+1];    // 初始化第一行        for(int i = 0; i < maxValue[0].length; i++) maxValue[0][i] = 0;    // 初始化第一列        for(int j = 0; j < maxValue.length; j++) maxValue[j][0] = 0;    // 放入背包(i——物品编号, j——背包容量)        for(int i = 1; i < maxValue.length; i++) {            for(int j = 1; j < maxValue[0].length; j++) {                // 第i个物品重量小于等于背包容量,可以放入                if(w[i-1] <= j) {                    // 放入第i个物品后,总价值变大——还是有点不太理解这个判断的意思?                    if(maxValue[i-1][j] < maxValue[i-1][j-w[i-1]] + v[i-1]) {                        // 背包价值变大                        maxValue[i][j] = maxValue[i-1][j-w[i-1]] + v[i-1];                        // 放入物品的位置                        path[i][j] = 1;                    // 放入第i个物品后,总价值不变                    } else {                        // 背包价值不变                        maxValue[i][j] = maxValue[i-1][j];                    }                // 第i个物品重量大于背包容量,无法放入                } else {                    // 背包价值不变                    maxValue[i][j] = maxValue[i-1][j];                }            }        }    // 遍历动态规划产生的"物品-容量-价值"数组        System.out.println("动态规划产生的maxValue[][]数组演变过程:");        for(int i = 0; i < maxValue.length; i++) {            for(int j = 0; j < maxValue[0].length; j++) {                System.out.print(maxValue[i][j] + "\t");            }            System.out.println();        }    // 放入物品位置的确定        int i = maxValue.length - 1;        int j = maxValue[0].length - 1;        while(i > 0 && j > 0) {            // 放入物品的位置——path[i][j] == 1            if(path[i][j] == 1) {                System.out.println("第 " + i + " 个物品放入背包, 背包已用容量 " + (j-1)                         + ", 该物品价值为 " + v[i-1] +", 该物品重量为 " + w[i-1]);                // 背包容量递减                j = j - w[i - 1];            }            // 物品编号递减            i--;        }        return maxValue[maxValue.length - 1][maxValue[0].length - 1];    }} 
public class Solution {    public static void main(String[] args) {        int capacity = 12;        int[] size = {2, 3, 5, 7};        System.out.println("背包最多装满空间: " + Solution.backPack(capacity, size));    }    /**     * 0-1背包问题     *      * 题目描述:     *      在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]     *      * 样例:     *      如果有4个物品[2, 3, 5, 7]     *      如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。     *      如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。     *      函数需要返回最多能装满的空间大小。     *      * @param c: 背包容量     * @param s: 物品大小数组     * @return     */    public static int backPack(int m, int[] A) {        // 输入参数校验        if(A == null || A.length == 0 || m <= 0) return 0;        // 物品数目        int n = A.length;        // 动态规划用到的"物品-容量-放入"数组        boolean[][] dp = new boolean[n + 1][m + 1];        dp[0][0] = true;        // 放入背包(i——物品编号, j——背包大小)        for(int i = 1; i <= n; i++){            for(int j = 0; j <= m; j++){                // 物品i大小小于等于背包容量, 可以放入背包                if(j >= A[i - 1] && dp[i - 1][j - A[i - 1]]) dp[i][j] = true;                else if(dp[i - 1][j]) dp[i][j] = true;            }        }        for(int i = m; i >= 0; i--) if(dp[n][i]) return i;        return 0;    }}
原创粉丝点击