题目:
假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。
当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。
例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。
请计算出粉刷完所有房子最少的花费成本。
示例 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
思路:
动态规划
当已知粉刷前 ii个房子的最小花费成本时,根据粉刷第 i+1 号房子的花费成本可以计算粉刷前 i + 1 个房子的最小花费成本,因此可以使用动态规划计算最小花费成本。
用dp[i][j] 表示粉刷第 0号房子到第 i号房子且第 i 号房子被粉刷成第 j种颜色时的最小花费成本。由于一共有 n 个房子和 3 种颜色,因此 0≤i<n,0≤j<3。
当只有第 00 号房子被粉刷时,对于每一种颜色,总花费成本即为将第 00 号房子粉刷成该颜色的花费成本,因此边界条件是:对于任意 0 \le j < 30≤j<3,\textit{dp}[0][j] = \textit{costs}[0][j]dp[0][j]=costs[0][j]。
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][0],dp[i−1][1])+costs[i][2]
计算结束时,dp[n−1] 中的最小值即为粉刷所有房子的最小花费成本。
当 i≥1 时,由于dp[i] 的计算只和 dp[i−1] 有关,因此可以使用滚动数组优化空间,将空间复杂度降低到 O(1)
java代码:
class Solution {
public int minCost(int[][] costs) {
int n = costs.length;
int[] dp = new int[3];
for (int i = 0; i < 3; i++) {
dp[i] = costs[0][i];
}
for (int i = 1; i < n; i++) {
int[] dpNew = new int[3];
dpNew[0] = Math.min(dp[1], dp[2]) + costs[i][0];
dpNew[1] = Math.min(dp[0], dp[2]) + costs[i][1];
dpNew[2] = Math.min(dp[0], dp[1]) + costs[i][2];
dp = dpNew;
}
return Arrays.stream(dp).min().getAsInt();
}
}
网友评论