LeetCode 5431. 给房子涂色 III(DP)

1. 题目

在一个小城市里,有 m 个房子排成一排,你需要给每个房子涂上 n 种颜色之一(颜色编号为 1 到 n )。
有的房子去年夏天已经涂过颜色了,所以这些房子不需要被重新涂色。

我们将连续相同颜色尽可能多的房子称为一个街区。(比方说 houses = [1,2,2,3,3,2,1,1] ,它包含 5 个街区 [{1}, {2,2}, {3,3}, {2}, {1,1}] 。)

给你一个数组 houses ,一个 m * n 的矩阵 cost 和一个整数 target ,其中:

  • houses[i]:是第 i 个房子的颜色,0 表示这个房子还没有被涂色。
  • cost[i][j]:是将第 i 个房子涂成颜色 j+1 的花费。

请你返回房子涂色方案的最小总花费,使得每个房子都被涂色后,恰好组成 target 个街区。
如果没有可用的涂色方案,请返回 -1 。

示例 1:
输入:houses = [0,0,0,0,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], 
m = 5, n = 2, target = 3
输出:9
解释:房子涂色方案为 [1,2,2,1,1]
此方案包含 target = 3 个街区,分别是 [{1}, {2,2}, {1,1}]。
涂色的总花费为 (1 + 1 + 1 + 1 + 5) = 9。

示例 2:
输入:houses = [0,2,1,2,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], 
m = 5, n = 2, target = 3
输出:11
解释:有的房子已经被涂色了,在此基础上涂色方案为 [2,2,1,2,2]
此方案包含 target = 3 个街区,分别是 [{2,2}, {1}, {2,2}]。
给第一个和最后一个房子涂色的花费为 (10 + 1) = 11。

示例 3:
输入:houses = [0,0,0,0,0], cost = [[1,10],[10,1],[1,10],[10,1],[1,10]], 
m = 5, n = 2, target = 5
输出:5

示例 4:
输入:houses = [3,1,2,3], cost = [[1,1,1],[1,1,1],[1,1,1],[1,1,1]], 
m = 4, n = 3, target = 3
输出:-1
解释:房子已经被涂色并组成了 4 个街区,分别是 [{3},{1},{2},{3}] ,
无法形成 target = 3 个街区。
 
提示:
m == houses.length == cost.length
n == cost[i].length
1 <= m <= 100
1 <= n <= 20
1 <= target <= m
0 <= houses[i] <= n
1 <= cost[i][j] <= 10^4

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/paint-house-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

  • dp[i][c][j]表示刷完i号房子,其颜色为 c时,产生j个街区的最小花费
class Solution {
public:
    int minCost(vector<int>& houses, vector<vector<int>>& cost, int m, int n, int target) {
        int i, j, c1, c2, mincost = INT_MAX;
        vector<vector<vector<int>>> dp(m, vector<vector<int>>(n+1, vector<int>(m+1, INT_MAX)));
        //初始化,第一个房子的情况
        if(houses[0] != 0)//已经刷过了
            dp[0][houses[0]][1] = 0;
        else//没有刷
            for(c1 = 1; c1 < n+1; ++c1)
                dp[0][c1][1] = cost[0][c1-1];
		//其余房子
        for(i = 1; i < m; i++) 
        {
            for(c1 = 1; c1 < n+1; c1++)//前一个房子的颜色
            {
                for(j = 1; j < m; j++)//几个 block
                {
                    if(dp[i-1][c1][j] == INT_MAX)
                        continue;
                    if(houses[i] != 0)//已经刷过颜色,没有费用
                    {
                        if(houses[i] == c1)//跟前一家颜色一样,街区不增加
                            dp[i][houses[i]][j] = min(dp[i][houses[i]][j], dp[i-1][c1][j]);
                        else
                            dp[i][houses[i]][j+1] = min(dp[i][houses[i]][j+1], dp[i-1][c1][j]);
                    }
                    else//没有刷过颜色
                        for(c2 = 1; c2 < n+1; c2++)//当前房子的颜色
                        {
                            if(c1 == c2)//跟前一家颜色一样,街区不增加,费用增加
                                dp[i][c2][j] = min(dp[i][c2][j], dp[i-1][c1][j]+cost[i][c2-1]);
                            else
                                dp[i][c2][j+1] = min(dp[i][c2][j+1], dp[i-1][c1][j]+cost[i][c2-1]);
                        }
                }
            }
        }
        for(c1 = 1; c1 < n+1; c1++)
            mincost = min(mincost, dp[m-1][c1][target]);
        return mincost==INT_MAX ? -1 : mincost;
    }
};

100 ms 16.9 MB

上一篇:力扣周赛 5431. 给房子涂色 III


下一篇:pandas快速入门