LeetCode 题解工作台
粉刷房子 III
在一个小城市里,有 m 个房子排成一排,你需要给每个房子涂上 n 种颜色之一(颜色编号为 1 到 n )。有的房子去年夏天已经涂过颜色了,所以这些房子不可以被重新涂色。 我们将连续相同颜色尽可能多的房子称为一个街区。(比方说 houses = [1,2,2,3,3,2,1,1] ,它包含 5 个街区…
2
题型
5
代码语言
3
相关题
当前训练重点
困难 · 状态·转移·动态规划
答案摘要
我们定义 表示将下标 的房子涂上颜色,最后一个房子的颜色为 ,且恰好形成 个街区的最小花费。那么答案就是 ,其中 的取值范围为 。初始时,我们判断下标为 的房子是否已经涂色,如果未涂色,那么 $f[0][j][1] = \textit{cost}[0][j - 1]$,其中 $j \in [1,..n]$。如果已经涂色,那么 $f[0][\textit{houses}[0]][1] = …
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路
题目描述
在一个小城市里,有 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.lengthn == cost[i].length1 <= m <= 1001 <= n <= 201 <= target <= m0 <= houses[i] <= n1 <= cost[i][j] <= 10^4
解题思路
方法一:动态规划
我们定义 表示将下标 的房子涂上颜色,最后一个房子的颜色为 ,且恰好形成 个街区的最小花费。那么答案就是 ,其中 的取值范围为 。初始时,我们判断下标为 的房子是否已经涂色,如果未涂色,那么 ,其中 。如果已经涂色,那么 。其他的 的值都初始化为 。
接下来,我们从下标 开始遍历,对于每个 ,我们判断下标为 的房子是否已经涂色:
如果未涂色,那么我们可以将下标为 的房子涂成颜色 ,我们枚举街区的数量 ,其中 ,并且枚举下标为 的房子的前一个房子的颜色 ,其中 ,那么我们可以得到状态转移方程:
如果已经涂色,那么我们可以将下标为 的房子涂成颜色 ,我们枚举街区的数量 ,其中 ,并且枚举下标为 的房子的前一个房子的颜色 ,其中 ,那么我们可以得到状态转移方程:
最后,我们返回 ,其中 ,如果所有的 的值都为 ,那么返回 。
时间复杂度 ,空间复杂度 。其中 , , 分别为房子的数量,颜色的数量,街区的数量。
class Solution:
def minCost(
self, houses: List[int], cost: List[List[int]], m: int, n: int, target: int
) -> int:
f = [[[inf] * (target + 1) for _ in range(n + 1)] for _ in range(m)]
if houses[0] == 0:
for j, c in enumerate(cost[0], 1):
f[0][j][1] = c
else:
f[0][houses[0]][1] = 0
for i in range(1, m):
if houses[i] == 0:
for j in range(1, n + 1):
for k in range(1, min(target + 1, i + 2)):
for j0 in range(1, n + 1):
if j == j0:
f[i][j][k] = min(
f[i][j][k], f[i - 1][j][k] + cost[i][j - 1]
)
else:
f[i][j][k] = min(
f[i][j][k], f[i - 1][j0][k - 1] + cost[i][j - 1]
)
else:
j = houses[i]
for k in range(1, min(target + 1, i + 2)):
for j0 in range(1, n + 1):
if j == j0:
f[i][j][k] = min(f[i][j][k], f[i - 1][j][k])
else:
f[i][j][k] = min(f[i][j][k], f[i - 1][j0][k - 1])
ans = min(f[-1][j][target] for j in range(1, n + 1))
return -1 if ans >= inf else ans
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | and space complexity depend on m, n, and target. Standard DP leads to O(m * n * target * n) time and O(m * target * n) space, reflecting iteration over houses, colors, and neighborhood states. |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Consider edge cases where houses are already painted and may limit valid neighborhood formation.
- question_mark
Check for impossibility early if initial painted houses exceed target neighborhoods.
- question_mark
Optimize state transitions to avoid redundant recalculations for all color combinations.
常见陷阱
外企场景- error
Ignoring already painted houses and adding paint costs incorrectly.
- error
Incorrectly incrementing neighborhood count when consecutive houses have the same color.
- error
Overlooking cases where forming exactly target neighborhoods is impossible, returning wrong cost.
进阶变体
外企场景- arrow_right_alt
Change the neighborhood definition to allow non-consecutive same-colored houses and track differently in DP.
- arrow_right_alt
Introduce additional constraints like limiting specific colors for certain houses.
- arrow_right_alt
Optimize for large n by pruning DP states using memoization of only feasible previous color transitions.