当前位置: 首页 > news >正文

「动态规划」如何求粉刷房子的最少花费?

LCR 091. 粉刷房子icon-default.png?t=N7T8https://leetcode.cn/problems/JEj789/description/

假如有一排房子,共n个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个n x 3的正整数矩阵costs来表示的。例如,costs[0][0]表示第0号房子粉刷成红色的成本花费;costs[1][2]表示第1号房子粉刷成绿色的花费,以此类推。请计算出粉刷完所有房子最少的花费成本。

  1. 输入:costs = [[17,2,17],[16,16,5],[14,3,19]],输出:10,解释:将0号房子粉刷成蓝色,1号房子粉刷成绿色,2号房子粉刷成蓝色。最少花费:2 + 5 + 3 = 10。
  2. 输入:costs = [[7,6,2]],输出:2

提示:costs.length == n,costs[i].length == 3,1 <= n <= 100,1 <= costs[i][j] <= 20。


我们用动态规划的思想来解决这个问题。

确定状态表示:根据经验和题目要求,我们用dp[i]表示粉刷完i位置的房子后,此时的最少花费。这可以细分为:

  • 用dp[i][0]表示:将i位置的房子粉刷成红色之后的最少花费。
  • 用dp[i][1]表示:将i位置的房子粉刷成蓝色之后的最少花费。
  • 用dp[i][2]表示:将i位置的房子粉刷成绿色之后的最少花费。

简单来说,在dp[i][j]中,i表示最后一个粉刷的房子的编号;j表示最后一个粉刷的房子中,粉刷的颜色的编号;dp[i][j]表示此时的最少花费

推导状态转移方程:我们考虑最近的一步,即粉刷完i - 1位置的房子之后的情况。

  • 考虑dp[i][0]。把i位置的房子粉刷成红色,所以只能把i - 1位置的房子粉刷成蓝色或者绿色。那么,把i位置的房子粉刷成红色之后的最少花费,就应该是把i - 1位置的房子粉刷成蓝色或者绿色之后的最少花费,两种情况的较小值,再加上把i位置粉刷成红色的花费。即dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i][0]。
  • 同理,dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i][1],dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i][2]。

综上所述:dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i][0],dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i][1],dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i][2]

初始化:根据状态转移方程,在计算dp[0][j],其中j的范围是[0, 2]时,会发生越界访问,所以要进行相应的初始化。

  • dp[0][0]表示把0位置的房子粉刷成红色后,此时的最少花费,显然dp[0][0] = costs[0][0]。
  • 同理dp[0][1] = costs[0][1],dp[0][2] = costs[0][2]。

综上所述:dp[0][0] = costs[0][0],dp[0][1] = costs[0][1],dp[0][2] = costs[0][2]

当然,我们可以在最前面添加一个辅助结点dp[0][j] = 0,其中j的范围是[0, 2]。这样,根据状态转移方程,以dp[i][0]为例,此时min(dp[0][1], dp[0][2]) = 0,辅助结点的值不影响结果,符合预期。

填表顺序:根据状态转移方程,对于dp[i][j]只依赖于dp[i - 1][j],j的范围是[0, 2]。那么,我们只需要从左往右填表

返回值:由于不确定把最后一个房子粉刷成什么颜色,根据状态表示,最终应返回把最后一个房子粉刷成红色、蓝色或者绿色这3种情况中,最少花费的最小值,即dp[n][j]的最小值,其中j的范围是[0, 2]。

细节问题:由于新增了一个辅助结点,此时dp表的规模就不是n x 3,而是(n + 1) x 3。同时需注意下标的映射关系,dp[i][j]对应的是costs[i - 1][j]

时间复杂度:O(N),空间复杂度:O(N)。

class Solution {
public:int minCost(vector<vector<int>>& costs) {int n = costs.size();// 创建dp表vector<vector<int>> dp(n + 1, vector<int>(3));// 填表for (int i = 1; i <= n; i++) {dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i - 1][0];dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i - 1][1];dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i - 1][2];}// 返回结果return min(dp[n][0], min(dp[n][1], dp[n][2]));}
};

相关文章:

  • WordPress 高级缓存插件 W3 Total Cache Pro 详细配置教程
  • rocketmq做了哪些事情来提高性能
  • 多模态大模型思路
  • 修复损坏的Excel文件比你想象的要简单,这里提供几种常见的修复方法
  • 最好用的搜题软件大学?8个公众号和软件推荐清单! #知识分享#知识分享#经验分享
  • ui自动化中,selenium进行元素定位,以及CSS,xpath定位总结
  • 记录移动端项目iOS端相对于安卓的各种兼容性问题
  • Llama模型家族之Stanford NLP ReFT源代码探索 (二)Intervention Layers层
  • Vim 快捷键
  • Java进阶_接口
  • MySQL周内训参照1、ER实体关系图与数据库模型图绘制
  • wma和mp3哪个音质好?让我告诉你哪个更胜一筹
  • CAN总线终端电阻作用
  • Redis基本操作介绍
  • CATIA入门操作案例——创成式曲面设计案例,吹风机的绘制,多截面曲面的绘制,曲面偏移和修剪
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 【Leetcode】104. 二叉树的最大深度
  • Brief introduction of how to 'Call, Apply and Bind'
  • Date型的使用
  • eclipse(luna)创建web工程
  • MD5加密原理解析及OC版原理实现
  • vue中实现单选
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 大型网站性能监测、分析与优化常见问题QA
  • 构建工具 - 收藏集 - 掘金
  • 缓存与缓冲
  • 回流、重绘及其优化
  • 配置 PM2 实现代码自动发布
  • 小程序开发中的那些坑
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • (02)vite环境变量配置
  • (Git) gitignore基础使用
  • (ibm)Java 语言的 XPath API
  • (八)c52学习之旅-中断实验
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (原)Matlab的svmtrain和svmclassify
  • (转)c++ std::pair 与 std::make
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • .DFS.
  • .NET C# 配置 Options
  • .net framework 4.8 开发windows系统服务
  • .Net Web项目创建比较不错的参考文章
  • .Net接口调试与案例
  • .Net转前端开发-启航篇,如何定制博客园主题
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • @EnableAsync和@Async开始异步任务支持
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • [100天算法】-x 的平方根(day 61)
  • [AMQP Connection 127.0.0.1:5672] An unexpected connection driver error occured
  • [Android] Upload package to device fails #2720
  • [C++内存管理]new,delete,operator new,opreator delete
  • [C语言]——函数递归
  • [Day 43] 區塊鏈與人工智能的聯動應用:理論、技術與實踐