DP-LeetCode265. 粉刷房子 II

1、题目描述

同类题:LeetCode256. 粉刷房子 https://blog.csdn.net/IOT_victor/article/details/106365741 (序列型)

假如有一排房子,共 n 个,每个房子可以被粉刷成 k 种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同

当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x k 的矩阵来表示的。

例如,costs[0][0] 表示第 0 号房子粉刷成 0 号颜色的成本花费;costs[1][2] 表示第 1 号房子粉刷成 2 号颜色的成本花费,以此类推。请你计算出粉刷完所有房子最少的花费成本。注意:所有花费均为正整数。

输入: [[1,5,3],[2,9,4]]
输出: 5
解释: 将 0 号房子粉刷成 0 号颜色,1 号房子粉刷成 2 号颜色。最少花费: 1 + 4 = 5; 
         或者将 0 号房子粉刷成 2 号颜色,1 号房子粉刷成 0 号颜色。最少花费: 3 + 2 = 5. 

进阶:您能否在 O(nk) 的时间复杂度下解决此问题?
 

2、代码详解

class Solution(object):
    def minCostII(self, costs):
        """
        :type costs: List[List[int]]
        :rtype: int
        """
        if not costs:
            return 0
        n = len(costs)  # 房子数 n
        k = len(costs[0])  # 颜色数 k
        INF = float('inf')
        dp = [[INF for _ in range(k)] for _ in range(n+1)]

        # init
        for i in range(k):
            dp[0][i] = 0

        id1, id2 = 0, 0  # 最小值和次小值的下标
        for i in range(1, n+1):
            min1 = INF  # 花费最小值,记录之前的dp,同时用 id1 记录 j 时的颜色
            min2 = INF  # 花费次小值

            for j in range(k):  # 找到上一个状态[i-1]的花费最小数和次小数
                if dp[i-1][j] < min1:
                    min2 = min1  # 将最小值 传给次小值
                    id2 = id1
                    min1 = dp[i-1][j]
                    id1 = j
                else:
                    if dp[i-1][j] < min2:
                        min2 = dp[i-1][j]
                        id2 = j

            for j in range(k):
                dp[i][j] = costs[i-1][j]  # 当前房子的花费,注意对齐下标,dp是n+1维,costs是n维

                if j != id1:  # 与上个状态最后的房子 不撞色,选最小值min1
                    dp[i][j] += min1
                else:  # 与上个状态最后的房子 撞色,选次小值min2
                    dp[i][j] += min2

        # res = INF
        # for i in range(k):
        #     res = min(res, dp[n][i])

        res = min(dp[n][:])

        return res


costs = [[14,2,11],[11,14,5],[14,3,10]]  # 三个屋子分别使用第1,2,1种颜色,花费2+5+3,总花费是10
s = Solution()
print(s.minCostII(costs))

优化:从O(NK*K)到O(NK),记录最小值和次小值

https://www.jiuzhang.com/solutions/paint-house-ii/#tag-highlight-lang-python

https://blog.csdn.net/qq_32424059/article/details/90441027

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值