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