假如有一排房子,共 n
个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。
当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3
的正整数矩阵 costs
来表示的。
例如,costs[0][0]
表示第 0 号房子粉刷成红色的成本花费;costs[1][2]
表示第 1 号房子粉刷成绿色的花费,以此类推。
请计算出粉刷完所有房子最少的花费成本。
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
示例 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
提示:
costs.length == n
costs[i].length == 3
1 <= n <= 100
1 <= costs[i][j] <= 20
思路:
采取dp,关键点:找出边界条件与状态转移方程。dp[i][j]:第i个房子粉刷为j颜色时的花费,保证前i-1个房子花费最少,0<=i<n;0<=j<=2,0,1,2代表三种粉刷颜色
边界条件:dp[0][j]=cost[0][j];
状态转移方程:(只看i与i-1)前i-1个房子的最小花费加上第i个房子j颜色时的花费。但第i个房子的粉刷颜色与第i-1个不同,i-1号房子只能粉刷两种颜色。
前i-1个房子最小花费:min(dp[i-1][(j+1)%3],dp[i-1][(j+2)%3]);因为第i个房子的粉刷颜色为j,则前一个i-1个房子粉刷颜色只能为(j+1)%3,(j+2)%3 //eg:j=2,则只能为(2+1)%3=0,(2+2)%3=1;故取这两种颜色的花费较小值作为前i-1个房子最小花费.
所以状态转移方程为:dp[i][j]=min(dp[i-1][(j+1)%3],dp[i-1][(j+2)%3])+cost[i][j];
class Solution { public: int minCost(vector<vector<int>>& costs) { int n=costs.size();//获得n(房子)的个数; int dp[100][3]; for(int j=0;j<3;j++)//边界条件 { dp[0][j]=costs[0][j]; } for(int i=1;i<n;i++) { for(int j=0;j<3;j++)//min函数用来比较两个参数的大小,并返回较小值,不能比较三个以上。 dp[i][j]=min(dp[i-1][(j+1)%3],dp[i-1][(j+2)%3])+costs[i][j]; } int ans=dp[n-1][0]; for(int j=1;j<=2;j++) { ans=min(ans,dp[n-1][j]); } return ans; } };
空间优化:
分析状态转移方程可知,dp[i]的值只和dp[i-1]有关,dp[i]的值只对应了三种粉刷颜色时的最小花费,所以可以利用两个保存3个颜色花费的数组,一个记录dp[i]时三种颜色对应的最小的花费,(newdp[j],j=0,1,2),一个记录dp[i-1]时三种颜色的最小花费。(dp[j],j=0,1,2),则状态转移方程转换为:newdp[j]=min(dp[(j+1)%3],dp[(j+2)%3])+costs[i][j];
/*优化:滚动数组优化空间,dp[i]计算只与dp[i-1]有关,所以用两个长度为3的数组 保存当前dp[i]与上一个dp[i-1]即可,空间复杂度降低到O(1)*/ class Solution { public: int minCost(vector<vector<int>>& costs) { int n = costs.size(); vector<int> dp(3);//dp[3]表示三种颜色对应的最小花费值 for(int j=0;j<=2;j++) { dp[j]=costs[0][j];//第一个dp[j],i=0时的三种颜色对应的最小花费 } for(int i=1;i<n;i++)//从第二个房子开始 { vector<int> newdp(3);//dp[i+1] for(int j=0;j<3;j++) { newdp[j]=min(dp[(j+1)%3],dp[(j+2)%3])+costs[i][j]; } dp=newdp;//dp[i]=dp[i+1]; } return *min_element(dp.begin(), dp.end());/*三种颜色对应最小花费值的最小值便为最终的最小花费*/ } };