返回

巧妙解题!轻松掌握 leetcode 1473. Paint House III (Python)

后端

导语:

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 解题的具体步骤:

  1. 初始化一个哈希表 memo,用于存储已经访问过的状态及其结果。
  2. 定义一个递归函数 dfs,它接收当前房屋的索引、当前涂装方案和已经涂成同一颜色的房屋数量作为参数。
  3. 如果当前状态已经存在于 memo 中,则直接返回其结果。
  4. 如果当前状态不存在于 memo 中,则计算该状态的结果并将其存储在 memo 中。
  5. 返回当前状态的结果。
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 这道题中,我们可以将每一种涂装方案作为一种状态,并使用动态规划来计算每一种状态的最小成本。

这里是如何使用动态规划解题的具体步骤:

  1. 定义一个二维数组 dp,其中 dp[i][j][k] 表示涂装前 i 间房屋,其中有 j 间房屋涂成同一颜色,当前房屋涂成第 k 种颜色的最小成本。
  2. 初始化 dp 数组:
    • dp[0][0][0] = 0
    • 对于所有其他状态,dp[i][j][k] = float('inf')
  3. 迭代计算每一种状态的最小成本:
    • 对于所有 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])
  4. 返回 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 和动态规划。两种解法各有优缺点,你可以根据自己的喜好选择一种来解决这道问题。希望这篇教程对你有帮助,如果你有任何问题,请随时留言。