剑指offer91:粉刷房子

题目:
假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。
当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。
例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。
请计算出粉刷完所有房子最少的花费成本。
示例一:
输入: costs = [[17,2,17],[16,16,5],[14,3,19]]
输出: 10
解释: 将 0 号房子粉刷成蓝色,1 号房子粉刷成绿色,2 号房子粉刷成蓝色。
最少花费: 2 + 5 + 3 = 10。
示例二:
输入: costs = [[7,6,2]]
输出: 2
分析:
该题求最小花费也就是最优解,因而这个问题适合于动态规划解决。
因为相邻的两幢房子不能被粉刷成相同的颜色,要计算粉刷到标号为i的房子时的成本,还需要考虑标号为i-1的房子的颜色,因此需要3个表达式即r(i),g(i),b(i),分别表示将标号为i的房子粉刷成红色,绿色和蓝色时粉刷标号从0到i的i+1幢房子的最少成本。当标号为i的房子被粉刷成红色时,标号为i-1的房子可以被粉刷成绿色或蓝色,因此r(i)=min(g(i-1),b(i-1))+costs[i][0],另外两个表达式同理。这三个表达式要求i>0,否则i-1没有意义。
左侧是costs表格(每一行代表的是每一幢房子,每一列代表颜色,每一个小格子代表每一幢房子在某个颜色下粉刷需要的成本),右侧是我们将要创建的dp表格,dp表格就是用来计算最小成本的,我们计算到dp表格最后一行,最后一行中的最小值就是房子花费的最小成本。
在这里插入图片描述
可以接着改进该算法,精简成两行三列的dp数组,降低空间复杂度,因为想得出dp数组下一行,只需要知道上一行数组的三列的值和costs数组即可,多余的空间也是浪费,具体详见代码的方法二。

代码:

public class minCost {
    
    
    public int minCost1(int[][] costs){
    
    
        if (costs.length == 0){
    
    
            return 0;
        }
        int[][] dp = new int[costs.length + 1][3];
        for (int i = 1; i <= costs.length; i++) {
    
    
            dp[i][0] = costs[i-1][0] +Math.min(dp[i-1][1],dp[i-1][2]);
            dp[i][1] = costs[i-1][1] +Math.min(dp[i-1][0],dp[i-1][2]);
            dp[i][2] = costs[i-1][2] +Math.min(dp[i-1][0],dp[i-1][1]);
        }
        return Math.min(dp[costs.length][0],Math.min(dp[costs.length][1],dp[costs.length][2]));
    }
    public int minCost2(int[][] costs) {
    
    
        if (costs.length == 0){
    
    
            return 0;
        }
        //将数组行数精简为2,因为只需要两行,列数精简为3,因为只需要三行。
        int[][] dp = new int[2][3];
        for (int j = 0; j < 3; j++) {
    
    
            dp[0][j] = costs[0][j];
        }
        for (int i = 1; i < costs.length; i++) {
    
    
            for (int j = 0; j < 3; j++) {
    
    
                int prev1 = dp[(i-1)%2][(j+2)%3];
                int prev2 = dp[(i-1)%2][(j+1)%3];
                dp[i%2][j] = Math.min(prev1,prev2)+costs[i][j];
            }
        }
        int last = (costs.length-1)%2;
        return Math.min(dp[last][0],Math.min(dp[last][1],dp[last][2]));
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Jiaodaqiaobiluo/article/details/122897315