8.动态规划_01

动态规划

题解来源: 代码随想录

https://programmercarl.com/0746.使用最小花费爬楼梯.html

746. 使用最小花费爬楼梯

class Solution {
    public int minCostClimbingStairs(int[] cost) {
       if (cost == null) {
           return 0;
       }
       int n = cost.length;
       if (n == 1) {
           return cost[0];
       }
       // dp[i] 代表上到第i个阶梯所需的最小花费
       int[] dp = new int[n];
       dp[0] = cost[0];
       dp[1] = cost[1];
       for (int i = 2 ; i < n; i++) {
        // 可以从第 i - 1 或者第 i - 2 步到达阶梯顶
           dp[i] = Math.min(dp[i - 1],dp[i - 2]) + cost[i];
        }
        return Math.min(dp[n - 1], dp[n - 2]);
    }
}

343. 整数拆分

	public int integerBreak(int n) {
        // dp[i] 代表整数 i 拆分后的最大乘积
        int[] dp = new int[n + 1];
        dp[2] = 1;
        for (int i = 3; i <= n; i++) {
            // j*(i-j)代表把i拆分为j和i-j两个数相乘
            // j*dp[i-j]代表把i拆分成j和继续把(i-j)这个数拆分,取(i-j)拆分结果中的最大乘积与j相乘
            for (int j = 1; j < i - 1; j++) {
                dp[i] = Math.max(dp[i], Math.max(dp[i - j], i - j) * j);
            }
        }
        return dp[n];
    }

背包理论

基础一

public static void main(String[] args) {
        int[] weight = {1, 3, 4};
        int[] value = {15, 20, 30};
        int bagSize = 4;
        bag(weight, value, bagSize);
    }

    public static void bag(int[] weight, int[] value, int bagSize) {
        // dp[i][j] 表示背包容量为 j 时,选取 0 - i 个物品装入背包的最大值;
        int[][] dp = new int[weight.length][bagSize + 1];
        // 背包只装一个物品的初始化
        for (int i = weight[0]; i <= bagSize; i++) {
            dp[0][i] = value[0];
        }
        // 顺序遍历物品
        for (int i = 1; i < weight.length; i++) {
            for (int j = 0; j <= bagSize; j++) {
                if (j < weight[i]) {  // 当前背包容量不足,装不下物品 i
                    dp[i][j] = dp[i - 1][j];
                } else {  // 当前背包容量充足,可以装下物品 i
                    // 可以选择装,或者不装物品 i
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
                }
            }
        }
        for (int i = 0; i < weight.length; i++) {
            for (int j = 0; j <= bagSize; j++) {
                System.out.print(dp[i][j] + "\t");
            }
            System.out.println();
        }
    }

基础二

一维数组遍历

	public static void bag_d(int[] weight, int[] value, int bagSize) {
        // dp[i] 代表背包重量为 i 时 所装物品的最大价值
        int[] dp = new int[bagSize + 1];
        // 遍历顺序:先遍历物品,再遍历背包容量
        for (int i = 0; i < weight.length; i++) {
            // 背包重量从后向前遍历
            // 从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了
            for (int j = bagSize; j >= weight[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
        }
        for (int j : dp) {
            System.out.print(j + "\t");
        }
    }

416. 分割等和子集

	public int integerBreak(int n) {
        // dp[i] 代表整数 i 拆分后的最大乘积
        int[] dp = new int[n + 1];
        dp[2] = 1;
        for (int i = 3; i <= n; i++) {
            // j * (i- j) 代表把 i 拆分为 j 和 i - j 两个数相乘
            // j * dp[i- j]代表把 i 拆分成 j 和继续把 (i - j) 这个数拆分,取(i - j)拆分结果中的最大乘积与j相乘
            for (int j = 1; j < i - 1; j++) {
                dp[i] = Math.max(dp[i], Math.max(dp[i - j], i - j) * j);
            }
        }
        return dp[n];
    }

1049. 最后一块石头的重量 II

	public int lastStoneWeightII(int[] stones) {
        if (stones == null) {
            return 0;
        }
        if (stones.length == 1) {
            return stones[0];
        }
        int sum = 0;
        for (int stone : stones) {
            sum += stone;
        }
        int target = sum >> 1;

        // dp[i] 容量为i的背包装的最大石头重量
        int[] dp = new int[target + 1];
        // 遍历物品
        for (int stone : stones) {
            // 遍历背包
            for (int j = target; j >= stone; j--) {
                // 重量是stones[i],价值是stones[i]
                // 两种情况,要么放,要么不放
                dp[j] = Math.max(dp[j], dp[j - stone] + stone);
            }
        }
        return sum - 2 * dp[target];
    }

2021.12.26 10:40

posted @ 2021-12-26 10:41  哟喝  阅读(44)  评论(0)    收藏  举报