【Leetcode每日一题】2021-05-03 1473 粉刷房子III - 困难 - 动态规划 (Python & C++)

该博客介绍了LeetCode的一道难题,即如何在已知每个房子原有颜色的情况下,以最低成本使得房子组成指定数量的街区。文章详细分析了动态规划的解决方案,包括两种情况:已粉刷的房子可以改变颜色和不可以改变颜色,并提供了优化后的算法,降低了时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来源:力扣

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

我们将连续相同颜色尽可能多的房子称为一个街区。(比方说 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

标签:动态规划

动态规划

题目中有一点说得不太明确,题目中说已经粉刷过的房子不需要再刷,题目本意应该是去年夏天刷过的房子不准再刷,说不需要感觉还是可以再被刷成其他颜色,所以说有一点不太明确。但是两种意思都挺有意思的,而且代码层面差别不大,这里我就把两种情况的个人解答都写出来了。
其实两种题目的动态规划解题思路大致是一样的:
  - 首先我们可以看出房子i的状态只跟房子i-1的状态有关,状态可以按target来分,即每个房子可以有target种状态,每种状态还可以分为n种颜色,所以这里要用三维DP → d p [ m ] [ t a r g e t ] [ n ] \rightarrow dp[m][target][n] dp[m][target][n]
  - 确定完状态下面就要推状态转移方程了。假设现在状态为dp[i][j][k],即房子i处于j街区时颜色为k的最小cost。首先按街区分为两种,j = 0j > 0
     → j = 0 \rightarrow j = 0 j=0: 说明房子i还处于第一街区,所以它的颜色必须和前一个房子i-1相同,所以 d p [ i ] [ j ] [ k ] = d p [ i − 1 ] [ j ] [ k ] + c o s t [ i ] [ k ] dp[i][j][k] = dp[i-1][j][k] + cost[i][k] dp[i][j][k]=dp[i1][j][k]+cost[i][k]
     → j > 0 \rightarrow j > 0 j>0: 此时房子已经不属于第一街区了,所以它的上一个房子i-1可以和i颜色相同(即i-1i属于同一街区j),也可以不同(即i-1属于i的上一个街区j-1),所以我们只需从所有可能性中选出cost最小的那一个所以 d p [ i ] [ j ] [ k ] = m i n ( [ d p [ i − 1 ] [ j ] [ k ] ] + [ d p [ i − 1 ] [ j − 1 ] [ c ]   f o r   c   i n   r a n g e ( n )   i f   c   ! =   k ] )

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值