剑指 Offer II 091. 粉刷房子

剑指 Offer II 091. 粉刷房子

动态规划
当前粉刷房子的花费可以由上一家粉刷房子的花费推导出来,所以可以使用动态规划求解这道题。
首先确定dp数组的含义,每个房子都可以被粉刷成三种颜色,那么自然而然可以得到数组
dp[i][j]
粉刷到第i个房子j颜色一共花的钱,i表示房子的数目,j表示颜色的种类。
初始化数组,就是第0间房子各种颜色的花费。
递推公式:dp[i][0] = costs[i][0] + Math.min(dp[i - 1][1], dp[i - 1][2]);
当前房子颜色为j时总花费 = 当前房子颜色为j时的花费 + 上一个房子颜色不为j(另外两种颜色)时的总花费的最小值
结果为最后一间房子三种颜色的最小值。
代码如下:

class Solution {
    public int minCost(int[][] costs) {
        int len = costs.length;
        int[][] dp = new int[len][3];
        for (int i = 0; i < 3; i++) {
            dp[0][i] = costs[0][i];
        }
        for (int i = 1; i < len;i++) {
            dp[i][0] = costs[i][0] + Math.min(dp[i - 1][1], dp[i - 1][2]);
            dp[i][1] = costs[i][1] + Math.min(dp[i - 1][0], dp[i - 1][2]);
            dp[i][2] = costs[i][2] + Math.min(dp[i - 1][0], dp[i - 1][1]);
        }
        return Math.min(dp[len - 1][0], Math.min(dp[len - 1][1], dp[len - 1][2]));
    }
}

由于当前状态完全由上一状态确定,所以可以使用滚动数组压缩状态,将空间复杂度降为1。
优化如下:

class Solution {
    public int minCost(int[][] costs) {
        int len = costs.length;
        int[][] dp = new int[2][3];
        for (int i = 0; i < 3; i++) {
            dp[0][i] = costs[0][i];
        }
        for (int i = 1; i < costs.length;i++) {
            dp[1][0] = costs[i][0] + Math.min(dp[0][1], dp[0][2]);
            dp[1][1] = costs[i][1] + Math.min(dp[0][0], dp[0][2]);
            dp[1][2] = costs[i][2] + Math.min(dp[0][0], dp[0][1]);
            for (int j = 0; j < 3; j++) {
                dp[0][j] = dp[1][j];
            }
        }
        return len == 1 ? Math.min(dp[0][0], Math.min(dp[0][1], dp[0][2])) : Math.min(dp[1][0], Math.min(dp[1][1], dp[1][2]));
    }
}

原文:https://leetcode.cn/problems/JEj789/solution/jian-dan-dp-by-nice-hermann9a2-81ol/

posted @ 2022-07-02 15:39  良人呐  阅读(24)  评论(0编辑  收藏  举报