【Leetcode剑指 Offer II 091】粉刷房子(动态规划 | 滚动数组)

一、题目

在这里插入图片描述

二、思路

(1)确定状态:
已知不同房子刷成不同颜色的价格矩阵cost,加上这种只需要求出【最值】的题目经常使用dp;因为每个房子能刷成三种颜色,即三种状态,加上不同的房子位置这个维度,可以令 d p [ j ] [ i ] dp[j][i] dp[j][i]二维数组(其中j取值为0,1,2)表示:第 i i i个房子粉刷为颜色j,并且这前i个房子的粉刷情况都是符合题意时,这i个房子所需要的最少话费成本。

(2)状态转移方程 d p [ i ] [ 0 ] = min ⁡ ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 2 ] ) + costs ⁡ [ i ] [ 0 ] d p [ i ] [ 1 ] = min ⁡ ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 2 ] ) + costs ⁡ [ i ] [ 1 ] d p [ i ] [ 2 ] = min ⁡ ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] ) + costs ⁡ [ i ] [ 2 ] \begin{aligned} d p[i][0] & =\min (d p[i-1][1], d p[i-1][2])+\operatorname{costs}[i][0] \\ d p[i][1] & =\min (d p[i-1][0], d p[i-1][2])+\operatorname{costs}[i][1] \\ d p[i][2] & =\min (d p[i-1][0], d p[i-1][1])+\operatorname{costs}[i][2] \end{aligned} dp[i][0]dp[i][1]dp[i][2]=min(dp[i1][1],dp[i1][2])+costs[i][0]=min(dp[i1][0],dp[i1][2])+costs[i][1]=min(dp[i1][0],dp[i1][1])+costs[i][2]神奇的是三个方程可以通过求余方法合为一个: d p [ i ] [ j ] = min ⁡ ( d p [ i − 1 ] [ ( j + 1 )   m o d   3 ] , d p [ i − 1 ] [ ( j + 2 )   m o d   3 ] ) + costs ⁡ [ i ] [ j ] d p[i][j]=\min (d p[i-1][(j+1) \bmod 3], d p[i-1][(j+2) \bmod 3])+\operatorname{costs}[i][j] dp[i][j]=min(dp[i1][(j+1)mod3],dp[i1][(j+2)mod3])+costs[i][j]计算到最后一个房子时,即 d p [ n − 1 ] [ j ] dp[n-1][j] dp[n1][j]数组的三个数的最小值为按规矩粉刷房子的最小总成本。因为当 i ≥ 1 i \geq 1 i1时, d p [ i ] dp[i] dp[i]的计算只和 d p [ i − 1 ] dp[i-1] dp[i1]有关,所以可以使用【滚动数组】优化计算复杂度,这个滚动数组即大小为颜色种类数。

(3)初始状态 + 边界情况
第0个房子左边木有房子,直接赋值当前房子的三种初值, d p [ k ] = c o s t s [ 0 ] [ k ] dp[k] = costs[0][k] dp[k]=costs[0][k]

(4)遍历顺序:ij都是从小到大遍历。

三、cpp代码

class Solution {
    
    
public:
    int minCost(vector<vector<int>>& costs) {
    
    
        int n = costs.size();
        vector<int>dp(3);
        //初始条件赋值
        for(int k = 0; k < 3; k++){
    
    
            dp[k] = costs[0][k];
        }
        //状态转移方程
        for(int i = 1; i < n; i++){
    
    
            vector<int> temp_vec(3);
            for(int j = 0; j < 3; j++){
    
    
                temp_vec[j] = min(dp[(j+1)%3], dp[(j+2)%3]) + costs[i][j];
            }
            dp = temp_vec;
        }
        auto ans_it = min_element(dp.begin(), dp.end());
        return *ans_it;
    }
};

四、Python代码

class Solution:
    def minCost(self, costs: List[List[int]]) -> int:
        # 赋值数组,简洁
        dp = costs[0]
        for i in range(1, len(costs)):
            temp_dp = []
            for j in range(3):
                temp_dp.append(min(dp[(j+1)%3], dp[(j+2)%3]) + costs[i][j])
            dp = temp_dp
        return min(dp)

猜你喜欢

转载自blog.csdn.net/qq_35812205/article/details/129650258