数据结构与算法

动态规划--背包问题

2019-12-30  本文已影响0人  暮想sun

一个背包的总容量为V,现在有N类物品,第i类物品的重量为weight[i],价值为value[i]。那么往该背包里装东西,怎样装才能使得最终包内物品的总价值最大?

0-1背包

每类物品最多只能装一次

    /**
     * 0-1背包问题
     *
     * 根据动态规划网格图,制定价值矩阵,第n个物品在v容量小的价值
     * dp[i][j] = (dp[i-1][j] > (dp[i-1][j-weight[i -1]]+value[i-1]))
     * ? dp[i-1][j]:(dp[i-1][j-weight[i-1]]+value[i-1])
     *
     * @param v      背包容量
     * @param n      物品种类
     * @param weight 物品重量
     * @param value  物品价值
     * @return
     */
    public static String zeroOnePack(int v, int n, int[] weight, int[] value) {

        //dp的数值,表示价值总和
        int[][] dp = new int[n + 1][v + 1];
        //i是物品,j是容量
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= v; j++) {
                //判断背包的重量是否超重,超重的情况下,最大价值,为上一个最大价值。
                if (weight[i - 1] > j) {
                    dp[i][j] = dp[i - 1][j];
                    continue;
                }
                
                //背包的当前容量的最大价值,与装入当前物品+恰能装进当前物品的容量的最大值。
                if (dp[i - 1][j] > dp[i - 1][j - weight[i - 1]] + value[i - 1]) {
                    dp[i][j] = dp[i - 1][j];
                } else {
                    dp[i][j] = dp[i - 1][j - weight[i - 1]] + value[i - 1];
                }

            }

        }

        int j = v;
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = n; i > 0; i--) {
            if (dp[i][j] > dp[i - 1][j]) {
                stringBuilder.append(i);
                j = j - weight[i - 1];
            }
        }

        return stringBuilder.toString();

    }

多重背包问题

物品数量有限制

    public static int manyPack(int v, int n, int[] weight, int[] value, int[] num) {
        //dp的数值,表示价值总和
        int[][] dp = new int[n + 1][v + 1];

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= v; j++) {

                if (weight[i - 1] > j) {
                    dp[i][j] = dp[i - 1][j];
                    continue;
                }

                //判断该物品在什么数量的情况下价值最大
                int maxV = Math.min(num[i - 1], j / weight[i - 1]);
                for (int k = 0; k <= maxV; k++) {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - k * weight[i - 1]] + k * value[i - 1]);
                }

            }

        }

        return dp[n][v];
    }

完全背包问题

每个物品数量无限制

    /**
     * 完全背包问题
     * 每个物品数量无限制
     *
     * 考虑di N行时,n产品可以考虑继续加入
     * dp[i][j] = (dp[i-1][j] > (dp[i][j-weight[i -1]]+value[i-1]))
     * ? dp[i-1][j]:(dp[i][j-weight[i-1]]+value[i-1])
     *
     * @param v
     * @param n
     * @param weight
     * @param value
     * @return
     */
    public static int completePack(int v, int n, int[] weight, int[] value) {

        //dp的数值,表示价值总和
        int[][] dp = new int[n + 1][v + 1];

        for (int i = 1; i <= n; i++) {

            for (int j = 1; j <= v; j++) {

                if (weight[i - 1] > j) {
                    dp[i][j] = dp[i - 1][j];
                    continue;
                }
                //当前物品加入判断价值行列
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - weight[i - 1]] + value[i - 1]);

            }

        }

        return dp[n][v];

    }
上一篇 下一篇

猜你喜欢

热点阅读