> 技术文档 > 动态规划 —— dp 问题-粉刷房子_力扣粉刷房子

动态规划 —— dp 问题-粉刷房子_力扣粉刷房子


江河入海,知识涌动,这是我参与江海计划的第11篇。

1. 剑指offer —— 粉刷房子

题目链接:

LCR 091. 粉刷房子 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/JEj789/description/


2. 题目解析

根据上图可以得到costs横坐标(行)是房子的号数,红色的下标是0,蓝色的下标是1,绿色的下标是2,粉刷房子只需要保证相邻的两个颜色不同就行


3.  算法原理 

状态表示:以某一个位置为结尾或者以某一个位置为起点

   

dp[i][0]表示:涂到i位置的时候,最后一个位置粉刷红色,此时的最小花费分

  

dp[i][1]表示:涂到i位置的时候,最后一个位置粉刷蓝色,此时的最小花费分

   

dp[i][2]表示:涂到i位置的时候,最后一个位置粉刷绿色,此时的最小花费分

2. 状态转移方程

  

根据最近的一步来划分问题:

   

1. dp[i][0]=min(dp[i-1][1] , dp[i-1][2]) + costs[i][0]

   

2. dp[i][1]=min(dp[i-1][0] , dp[i-1][2]) + costs[i][1]

   

3. dp[i][2]=min(dp[i-1][1] , dp[i-1][0]) + costs[i][2]

   

3. 初始化 :把dp表填满不越界,让后面的填表可以顺利进行

    

我们可以在前面再额外的加上一个虚拟节点   

本题初始化为:0

  

本题的下标映射关系:因为本题给了一个数组,而我们又额外的加上一个虚拟节点 ,所以我们的下标都统一往右边移动了一位,如果想找回之前对应的位置,那么下标需要进行统一减1

4. 填表顺序 

    

本题的填表顺序是:从左往右,三个表同时填(因为填写原数组第一个节点的值是需要另外两个数组虚拟节点的值)

5. 返回值 :题目要求 + 状态表示    

    

本题的返回值是:min(dp[n][0], min(dp[n][1], dp[n][2]))


4. 代码 

动态规划的固定四步骤:1.  创建一个dp表

                                        2. 在填表之前初始化

                                        3. 填表(填表方法:状态转移方程)

                                        4. 确定返回值

class Solution {public: int minCost(vector<vector>& costs) { int n = costs.size(); //1.  创建一个规模(n+1*3)的dp表 vector<vector>dp(n + 1, vector(3));//n+1:多加了一个虚拟节点 //2. 初始化为0,vector默认为0 //3. 填表(填表方法:状态转移方程) for (int i = 1; i <= n; i++) { //下标都-1是因为数组前面加了一个虚拟节点 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]; } //4. 确定返回值 return min(dp[n][0], min(dp[n][1], dp[n][2])); }};

完结撒花~