力扣每日一题0625-091. 粉刷房子

190 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情

假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。

当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。

例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。

请计算出粉刷完所有房子最少的花费成本。

示例 1:

输入:costs = [[17,2,17],[16,16,5],[14,3,19]]
输出: 10
解释: 将 0 号房子粉刷成蓝色,1 号房子粉刷成绿色,2 号房子粉刷成蓝色。
     最少花费: 2 + 5 + 3 = 10

示例 2:

输入:costs = [[7,6,2]]
输出: 2

动态规划

每个房子可以被粉刷成三种颜色中的一种,需要计算在满足相邻房子的颜色不同的情况下粉刷所有房子的最小花费成本。由于当已知粉刷前 ii 个房子的最小花费成本时,根据粉刷第 i+1i+1 号房子的花费成本可以计算粉刷前 i+1i+1 个房子的最小花费成本,因此可以使用动态规划计算最小花费成本。

由于每个房子可以被粉刷成三种颜色中的一种,因此需要分别考虑粉刷成三种颜色时的最小花费成本。

dp[i][j]\textit{dp}[i][j] 表示粉刷第 00 号房子到第 ii 号房子且第 ii 号房子被粉刷成第 jj 种颜色时的最小花费成本。由于一共有 nn 个房子和 33 种颜色,因此 0i<n0j<30≤i<n,0≤j<3

当只有第 00 号房子被粉刷时,对于每一种颜色,总花费成本即为将第 000 号房子粉刷成该颜色的花费成本,因此边界条件是:对于任意 0j<30 \le j < 3dp[0][j]=costs[0][j]\textit{dp}[0][j] = \textit{costs}[0][j]

对于 1i<n1 \le i < n,第 ii 号房子和第 i1i−1 号房子的颜色必须不同,因此当第 iii 号房子被粉刷成某一种颜色时,第 i1i−1 号房子只能被粉刷成另外两种颜色之一。

var minCost = function(costs) {
    const n = costs.length;
    let dp = new Array(3).fill(0);
    for (let j = 0; j < 3; j++) {
        dp[j] = costs[0][j];
    }
    for (let i = 1; i < n; i++) {
        const dpNew = new Array(3).fill(0);
        for (let j = 0; j < 3; j++) {
            dpNew[j] = Math.min(dp[(j + 1) % 3], dp[(j + 2) % 3]) + costs[i][j];
        }
        dp = dpNew;
    }
    return parseInt(_.min(dp));
};