python3实现一道粉刷房子动态规划算法题

假如有一排房子,共 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.

首先,我们考虑到直观的动态规划。
就是第一行找到最优最小值,然后递归到第二行,递归到第三行,但是这道题显然不行,由于第一行选择会限制第二行选择
因此换一种思路,将上一行所有的情况暂存(包括最优值),纳入下一行考察范围内,然后筛选掉非最优值。
ps:这里还有优化空间,待会讨论。

我们找到一个 O(n*k^2) 的动态规划解法,这个解法就是粉刷房子 解法的一个简单扩展。建立一个二维数组dp[i][k],其中i表示前i座房子,k表示该房子粉刷成颜色k的情况下前i座房子的最小花费,易得状态转移方程:

dp[i][k] = Math.min(dp[i-1][m]) + costs[i][k]
m取值范围是为[0, k-1], [k+1, costs[i].length-1即costs数组列数]

python3实现:

class Solution:
    def minCostII(self, costs: List[List[int]]) -> int:
        if not(costs):
            return 0
        dp=[]
        row=len(costs)
        col=len(costs[0])
        dp=[[] for i in range(row)]
        helper=[]
        for i in range(col):
            helper.append(float('inf'))
        for i in range(row):
            for j in range(col):
                helper[j]=(float('inf'))
                if i==0:
                    dp[i].append(costs[0][j])
                    
                else:
                    k=j
                    for m in range(k):
                        helper[m]=(dp[i-1][m])+costs[i][k]
                    for m in range(k+1,col):
                        helper[m]=(dp[i-1][m])+costs[i][k]
                    
                    dp[i].append(min(helper))

        return min(dp[row-1])

更好的优化建议:实际上,下一行只会受到上一行最小值和次小值的影响,可以通过减少helper写入次数来优化算法。

思路来源:
作者:ellery0924
链接:https://leetcode-cn.com/problems/two-sum/solution/javascript-onkfu-za-du-jie-fa-by-ellery0924/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态规划算法是一种解决最优化问的方法,它通常用于求解具有重叠子问和最优子结构性质的问Python是一种简单易学的编程语言,可以很方便地实现动态规划算法。 以下是Python实现动态规划算法的一般步骤: 1. 定义问:首先需要明确问的定义和目标,例如最小化成本、最大化收益等。 2. 确定状态:将问划分为若干个子问,并定义状态来描述每个子问的属性和特征。通常,状态可以用一个或多个变量来表示。 3. 状态转移方程:根据问的最优子结构性质,设计状态转移方程来描述各个子问之间的关系。状态转移方程通常使用递推公式来表达。 4. 初始化:设置初始状态,以便递推计算。 5. 计算最终结果:根据状态转移方程,递推计算每个子问的最优解,最终得到整个问的最优解。 以下是一个Python实现动态规划算法的示例代码,用于求解斐波那契数列的第n项: ```python def fibonacci(n): if n <= 1: return n else: # 初始化状态 f = [0] * (n+1) f[0], f[1] = 0, 1 # 状态转移方程 for i in range(2, n+1): f[i] = f[i-1] + f[i-2] # 计算最终结果 return f[n] ``` 在这个示例代码中,我们首先定义了斐波那契数列的问:求解斐波那契数列的第n项。然后,我们确定了状态:我们使用一个列表f来保存每个斐波那契数列的项。f[i]表示第i项的值。 接下来,我们设计了状态转移方程:f[i] = f[i-1] + f[i-2]。这个方程表达了斐波那契数列的递推关系。 接着,我们初始化了状态:我们将f[0]和f[1]分别初始化为0和1。 最后,我们计算最终结果:我们使用状态转移方程递推计算每个斐波那契数列的项,最终得到第n项的值。 这个示例代码展示了Python实现动态规划算法的基本思路和步骤。在实际应用中,我们需要根据具体问进行相应的调整和优化,以得到更高效和可靠的算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值