题目描述
题目链接:LCR 091. 粉刷房子

题目解析
根据图示,costs 数组的行代表房子的编号,列索引分别对应红色(0)、蓝色(1)、绿色(2)。粉刷房子只需保证相邻两个房子颜色不同即可。

算法原理
状态表示
- dp[i][0]:涂到第 i 个位置时,最后一个位置粉刷红色的最小花费。
- dp[i][1]:涂到第 i 个位置时,最后一个位置粉刷蓝色的最小花费。
- dp[i][2]:涂到第 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][1], dp[i-1][0]) + costs[i][2]
初始化
为了简化边界处理,在 dp 表前增加一个虚拟节点。本题初始化为 0。下标映射关系:由于增加了虚拟节点,原数组下标需统一减 1 进行访问。
填表顺序
从左往右,三个状态同时更新。
返回值
返回最后一个房子三种颜色的最小花费:min(dp[n][0], min(dp[n][1], dp[n][2]))。
代码实现
动态规划的固定四步骤:创建 dp 表、初始化、填表、确定返回值。
class Solution {
public:
int minCost(vector<vector<int>>& costs) {
int n = costs.size();
// 1. 创建一个规模 (n+1)*3 的 dp 表
vector<vector<int>> dp(n + 1, vector<int>(3));
( i = ; i <= n; i++) {
dp[i][] = (dp[i - ][], dp[i - ][]) + costs[i - ][];
dp[i][] = (dp[i - ][], dp[i - ][]) + costs[i - ][];
dp[i][] = (dp[i - ][], dp[i - ][]) + costs[i - ][];
}
(dp[n][], (dp[n][], dp[n][]));
}
};


