力扣 LCR 091. 粉刷房子 —— 动态规划入门详解

发布时间:2026/11/5 10:11:03

力扣 LCR 091. 粉刷房子 —— 动态规划入门详解 引言动态规划是算法面试中的拦路虎许多初学者不知从何下手。今天讲解的「力扣 91. 粉刷房子」正是 DP 入门的绝佳练习题。它不像背包问题需要纠结容量维度而是用最朴素的二维 DP 表格清晰展示了状态定义、初始化、转移和返回的完整流程。无论你是算法新手还是面试备战者这篇文章都会带你一步步拆解题目让你真正理解 DP 的核心思想。让我们从一道题开始打通动态规划的任督二脉摘要本文详细解析力扣 91「粉刷房子」的 DP 解法。给定n×3成本矩阵求相邻颜色不同时的最小总花费。定义dp[i][j]为第i个房子刷颜色j的最小花费转移方程dp[i][j]costs[i][j]min(dp[i-1][k]) (k≠j)。通过示例手动推导 DP 表格并提供二维数组和 O(1) 滚动数组两种代码实现。重点总结三个易错点维度理解、返回值、三数取最小值。时间 O(n)空间可优化至 O(1)目录一、题目描述二、动态规划思路1. 为什么用 DP2. DP 数组的定义3. DP 数组的构造以示例为例4. 状态转移方程三、Java 代码实现四、代码优化空间压缩五、易错点总结特别重要⚠️ 注意点 1DP 数组的构造维度⚠️ 注意点 2返回值不是 dp[n-1][2]⚠️ 注意点 3三个数取最小值的写法六、复杂度分析总结一、题目描述假如有一排房子共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二、动态规划思路1. 为什么用 DP这道题满足最优子结构第i个房子刷某种颜色的最小花费只依赖于第i-1个房子刷其他两种颜色的最小花费。因此我们可以用动态规划从前往后依次推导。2. DP 数组的定义我们定义一个二维数组dpdp[i][j]表示粉刷完前 i 个房子0 ~ i且第 i 个房子刷成颜色 j 时的最小总花费。其中i表示房子编号范围0 ~ n-1j表示颜色0红色1蓝色2绿色3. DP 数组的构造以示例为例输入costs [[17,2,17], [16,16,5], [14,3,19]]我们手动构造出dp数组房子 \ 颜色红色蓝色绿色0号房子172171号房子183372号房子211037推导过程初始化第一行第 0 号房子刷任意颜色花费就是它本身的成本。→dp[0] [17, 2, 17]第二行1号房子刷红色16 min(dp[0][1], dp[0][2]) 16 min(2,17) 18刷蓝色16 min(dp[0][0], dp[0][2]) 16 min(17,17) 33刷绿色5 min(dp[0][0], dp[0][1]) 5 min(17,2) 7第三行2号房子刷红色14 min(dp[1][1], dp[1][2]) 14 min(33,7) 21刷蓝色3 min(dp[1][0], dp[1][2]) 3 min(18,7) 10刷绿色19 min(dp[1][0], dp[1][1]) 19 min(18,33) 37最终最后一个房子2号房子的最小花费是min(21, 10, 37) 104. 状态转移方程dp[i][j] costs[i][j] min(dp[i-1][k]) 其中 k ≠ j也就是说当前房子刷颜色j的总花费 当前房子刷颜色j的成本 上一个房子刷另外两种颜色的较小值。三、Java 代码实现public class Main { public static void main(String[] args) { int[][] costs {{17, 2, 17}, {16, 16, 5}, {14, 3, 19}}; System.out.println(minCost(costs)); // 输出 10 } public static int minCost(int[][] costs) { int M costs.length; // 房子数量 int N 3; // 颜色数量红、蓝、绿 // dp[i][j]前 i 个房子第 i 个房子刷颜色 j 的最小总花费 int[][] dp new int[M][N]; // 1. 初始化第一行 for (int j 0; j N; j) { dp[0][j] costs[0][j]; } // 2. 从第二个房子开始递推 for (int i 1; i M; i) { for (int j 0; j N; j) { int prevMin; if (j 0) { // 当前刷红色上一个只能是蓝色或绿色 prevMin Math.min(dp[i-1][1], dp[i-1][2]); } else if (j 1) { // 当前刷蓝色上一个只能是红色或绿色 prevMin Math.min(dp[i-1][0], dp[i-1][2]); } else { // 当前刷绿色上一个只能是红色或蓝色 prevMin Math.min(dp[i-1][0], dp[i-1][1]); } dp[i][j] costs[i][j] prevMin; } } // 3. 返回最后一个房子的最小花费 return Math.min(dp[M-1][0], Math.min(dp[M-1][1], dp[M-1][2])); } }运行结果四、代码优化空间压缩因为dp[i]只依赖于dp[i-1]我们可以用一维数组滚动更新降低空间复杂度到O(1)public static int minCost(int[][] costs) { int n costs.length; int[] dp new int[3]; // 初始化第一行 dp[0] costs[0][0]; dp[1] costs[0][1]; dp[2] costs[0][2]; for (int i 1; i n; i) { int prev0 dp[0], prev1 dp[1], prev2 dp[2]; dp[0] costs[i][0] Math.min(prev1, prev2); dp[1] costs[i][1] Math.min(prev0, prev2); dp[2] costs[i][2] Math.min(prev0, prev1); } return Math.min(dp[0], Math.min(dp[1], dp[2])); }五、易错点总结特别重要⚠️ 注意点 1DP 数组的构造维度本题虽然只有一个“房子数量”维度但因为每个状态有 3 种颜色选择所以用二维数组dp[n][3]来记录。不要误以为需要“物品 容量”两个维度那是 01 背包的思路这里没有容量限制。⚠️ 注意点 2返回值不是dp[n-1][2]很多同学想当然地认为最后一个元素就是答案但这是错误的最后一个房子有三种可能颜色应该取三种颜色中的最小值return Math.min(dp[M-1][0], Math.min(dp[M-1][1], dp[M-1][2]));⚠️ 注意点 3三个数取最小值的写法Java 中Math.min()只支持两个参数取三个数最小值要嵌套Math.min(a, Math.min(b, c))六、复杂度分析时间复杂度O(n * 3) O(n)只需要遍历每个房子一次空间复杂度二维数组版O(n * 3) O(n)一维滚动数组版O(1)总结这道题是动态规划入门的经典题目核心思想是定义dp[i][j]表示第i个房子刷颜色j时的最小花费状态转移只依赖于前一个房子的两种颜色最后取最后一个房子的三种颜色中的最小值掌握了这道题后续遇到“打家劫舍”、“股票买卖”等经典 DP 问题思路也会更加清晰。希望这篇文章能帮助你更好地理解动态规划如果有问题欢迎留言讨论
延伸阅读

更多相关文章

2026/11/1 1:52:12

基于simulink的双向DC/AC接口变换器的系统效率

### 手把手教你学Simulink--直流微电网中双向DC/AC接口变换器的电压稳定控制 #### 摘要 随着能源转型的推进,直流微电网在分布式能源接入与供电可靠性提升方面发挥着日益重要的作用。双向DC/AC接口变换器作为直流微电网与交流电网能量交互的关键设备,其电压稳定控制对于保障…

2026/10/30 9:36:48

KVM主题:大页内存HugePages配置实践

KVM主题:大页内存HugePages配置实践 在虚拟化环境中,内存管理是影响性能的关键因素之一。KVM(Kernel-based Virtual Machine)作为Linux内核中的一个虚拟化模块,为虚拟机提供了高效的硬件虚拟化支持。为了进一步提升KVM…

2026/11/1 17:42:13

【Python自动化】安全库存阈值不同?库管/小白1个脚本预警

为什么你需要这个脚本 管多品类库存有多痛苦? 在仓库、仓库管理系统中管理货品时,出现令库管烦恼的问题是:把所有货品的安全库存阈值(即剩下多少件就预警且提示该补货/进货)设为统一标准,导致销量快的货总…

2026/11/5 10:08:45

前端开发者的AI Agent转型指南:技能升级,价值翻倍!

本文探讨了AI Agent的兴起如何改变前端开发者的价值定位。虽然AI能自动化简单的前端工作,但异步思维、流式处理、组件化设计和用户交互理解等前端核心技能,正是AI Agent应用开发的关键。文章指出,前端开发者无需转行,只需升级现有…

2026/11/5 10:08:45

Ceph搭建-Ubuntu 24.04.3

主机名IP 地址角色ceph-node1172.19.0.61MON, MGR, OSD, 管理节点ceph-node2172.19.0.62MON, MGR, OSDceph-node3172.19.0.63MON, MGR, OSD一、系统初始化1、安装系统依赖sudo apt update sudo apt install -y podman chrony lvm2 python3 sudo systemctl enable --now chrony/…

2026/11/5 10:03:39

附录 A · 工具速查表

附录导读本附录是混淆工具和反混淆工具的快速索引,按用途分类,相当于一本"工具字典":第 1 节:混淆工具——把代码变难分析的"加固方"武器;第 2 节:反混淆工具——把混淆代码还原回去的…

2026/11/5 10:03:39

PDO属性设置全解析:高效数据库操作秘诀

PDO::关于PHP的PDO这种技术, 它有一份参考手册。PDO:: — 设置属性(PHP 5 > 5.1.0, PECL pdo > 0.1.0)说明语法bool PDO::setAttribute ( int $attribute , mixed $value )我们需要把数据库句柄的属性给设置好。在下文之中, 会列举出一些可以被大家所用到的通用的属性内容…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑