巧妙解题!轻松掌握 leetcode 1473. Paint House III (Python)
2023-10-23 12:01:03
导语:
leetcode 1473. Paint House III 是 LeetCode 中一道经典的算法题,旨在考察你对动态规划和搜索算法的理解。这道题要求你在给定一组房子的成本和邻近房子的限制条件下,找到一种最优的涂装方案,使总成本最小。
本篇文章将为你提供两种解题思路:记忆化 DFS 和动态规划,并使用 Python 代码进行实现。在深入了解解法之前,我们先来看一下这道题的具体
题目:
给你一个整数 n,表示有 n 间房屋排成一排。每一间房屋都可以被涂成三种颜色之一:红色、蓝色或绿色。
给你一个 n x 3 的整数矩阵 costs,表示涂装第 i 间房屋的成本。
还给你一个数组 targetSize,它包含整数 target,表示在整个房屋排中,最多可以有多少间房屋被涂成同一颜色。
返回一个整数,表示按照给定限制条件,给房屋涂装所需要的最小总成本。
示例 1:
输入:costs = [[17,2,17],[16,16,5],[14,3,19]],targetSize = 2
输出:10
解释:成本最小的涂装方案为 [17, 2, 5, 14, 3, 19]。
示例 2:
输入:costs = [[7,6,2]],targetSize = 3
输出:5
解法一:记忆化 DFS
记忆化 DFS 是一种经典的搜索算法,它通过记录已经访问过的状态并保存其结果,避免重复计算,从而提高搜索效率。
在 leetcode 1473. Paint House III 这道题中,我们可以将每一种涂装方案作为一种状态,将已经访问过的状态保存起来,以便下次访问时直接读取结果。
这里是如何使用记忆化 DFS 解题的具体步骤:
- 初始化一个哈希表 memo,用于存储已经访问过的状态及其结果。
- 定义一个递归函数 dfs,它接收当前房屋的索引、当前涂装方案和已经涂成同一颜色的房屋数量作为参数。
- 如果当前状态已经存在于 memo 中,则直接返回其结果。
- 如果当前状态不存在于 memo 中,则计算该状态的结果并将其存储在 memo 中。
- 返回当前状态的结果。
def minCost(costs, targetSize):
"""
:type costs: List[List[int]]
:type targetSize: int
:rtype: int
"""
n = len(costs)
memo = {}
def dfs(i, state, same):
if i == n:
return 0 if same <= targetSize else float('inf')
if (i, state, same) in memo:
return memo[(i, state, same)]
result = float('inf')
for color in range(3):
if state & (1 << color):
result = min(result, dfs(i + 1, state, same))
else:
result = min(result, costs[i][color] + dfs(i + 1, state | (1 << color), same + 1))
memo[(i, state, same)] = result
return result
return dfs(0, 0, 0)
解法二:动态规划
动态规划是一种自底向上的算法,它将问题分解成更小的子问题,并逐步求解这些子问题,最终解决整个问题。
在 leetcode 1473. Paint House III 这道题中,我们可以将每一种涂装方案作为一种状态,并使用动态规划来计算每一种状态的最小成本。
这里是如何使用动态规划解题的具体步骤:
- 定义一个二维数组 dp,其中 dp[i][j][k] 表示涂装前 i 间房屋,其中有 j 间房屋涂成同一颜色,当前房屋涂成第 k 种颜色的最小成本。
- 初始化 dp 数组:
- dp[0][0][0] = 0
- 对于所有其他状态,dp[i][j][k] = float('inf')
- 迭代计算每一种状态的最小成本:
- 对于所有 i 从 1 到 n
- 对于所有 j 从 0 到 targetSize
- 对于所有 k 从 0 到 2
- 如果 dp[i - 1][j][k] 不为 float('inf')
- 对于所有 l 从 0 到 2
- 如果 k != l 或 j < targetSize
- dp[i][j + (k == l)][l] = min(dp[i][j + (k == l)][l], dp[i - 1][j][k] + costs[i - 1][l])
- 如果 k != l 或 j < targetSize
- 对于所有 l 从 0 到 2
- 如果 dp[i - 1][j][k] 不为 float('inf')
- 对于所有 k 从 0 到 2
- 对于所有 j 从 0 到 targetSize
- 对于所有 i 从 1 到 n
- 返回 dp[n][targetSize][0]
def minCost(costs, targetSize):
"""
:type costs: List[List[int]]
:type targetSize: int
:rtype: int
"""
n = len(costs)
dp = [[[float('inf')] * 3 for _ in range(targetSize + 1)] for _ in range(n + 1)]
dp[0][0][0] = 0
for i in range(1, n + 1):
for j in range(targetSize + 1):
for k in range(3):
if dp[i - 1][j][k] != float('inf'):
for l in range(3):
if k != l or j < targetSize:
dp[i][j + (k == l)][l] = min(dp[i][j + (k == l)][l], dp[i - 1][j][k] + costs[i - 1][l])
return dp[n][targetSize][0]
总结:
以上就是 leetcode 1473. Paint House III 这道题的两种解法:记忆化 DFS 和动态规划。两种解法各有优缺点,你可以根据自己的喜好选择一种来解决这道问题。希望这篇教程对你有帮助,如果你有任何问题,请随时留言。