1. 问题背景与核心需求
粉刷房子问题是一个经典的动态规划应用场景,它模拟了现实中的房屋装修决策过程。假设我们有n栋房子排成一列,每栋房子可以用k种不同颜色中的一种进行粉刷。相邻的两栋房子不能粉刷成相同的颜色。我们需要计算出粉刷所有房子的最低总成本。
这个问题的实际意义非常直观:在装修小区时,物业公司需要权衡材料成本和美观要求。不同颜色的油漆价格不同,同时又要避免相邻房屋颜色雷同造成的视觉单调。如何在预算和美观之间找到平衡点,正是这个问题要解决的核心矛盾。
从算法角度看,这个问题考察的是在相邻元素存在约束条件下的最优解计算能力。它比基础的单序列动态规划问题更复杂,因为每个位置的决策会影响后续多个步骤的选择空间。这类多状态转移问题在实际工程中非常常见,比如资源调度、路径规划等领域都会遇到类似模式。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动态规划解法设计思路
2.1 状态定义与转移方程
对于这类多状态决策问题,我们需要设计一个二维的dp数组:
- dp[i][j] 表示粉刷前i栋房子,且第i栋房子使用颜色j时的最小总成本
状态转移方程的核心思想是:当前房子的粉刷成本,加上前i-1栋房子在非j颜色情况下的最小总成本。具体可以表示为:
dp[i][j] = cost[i][j] + min(dp[i-1][k]) 其中k != j
这个方程反映了动态规划的两个关键特性:
- 最优子结构:当前最优解包含子问题的最优解
- 无后效性:当前决策只关心前一状态,不关心如何到达前一状态
2.2 初始化与边界条件处理
初始状态的处理需要特别注意:
- 第一栋房子没有前置约束,所以dp[0][j] = cost[0][j] 对所有颜色j成立
- 后续房子的计算需要考虑颜色不相同的约束
边界情况包括:
- 只有一栋房子时,直接返回各颜色成本的最小值
- 颜色数量为1时,若房子数量大于1则无解(因为无法满足相邻不同色的约束)
3. C++实现详解
3.1 基础实现代码
cpp复制int minCost(vector<vector<int>>& costs) {
if (costs.empty()) return 0;
int n = costs.size(), k = costs[0].size();
vector<vector<int>> dp(n, vector<int>(k, 0));
// 初始化第一栋房子
for (int j = 0; j < k; ++j) {
dp[0][j] = costs[0][j];
}
// 动态规划过程
for (int i = 1; i < n; ++i) {
for (int j = 0; j < k; ++j) {
int min_prev = INT_MAX;
for (int m = 0; m < k; ++m
