房屋染色 II
题目:
这里有n个房子在一列直线上,现在我们需要给房屋染色,共有k种颜色。每个房屋染不同的颜色费用也不同,你希望每两个相邻的房屋颜色不同,但是这样可能会使得成本上升。因此你决定可以有一个长度不超过t的区间,这之间的房屋可以染成同一种颜色。
费用通过一个nxk 的矩阵给出,比如cost[0][0]表示房屋0染颜色0的费用,cost[1][2]表示房屋1染颜色2的费用。
样例
样例1
输入:
costs = [[14,2,11],[11,14,5],[14,3,10]]
输出: 10
说明:
三个屋子分别使用第1,2,1种颜色,总花费是10。
样例2
输入:
costs = [[5]]
输出: 5
说明:
只有一种颜色,一个房子,花费为5
解题思路:和房屋染色类似,只是从3种颜色变成了k种颜色,因为每一次都要遍历k种颜色寻找最小花费,所以做了优化先将最小值和次小值找到然后再进行dp数组的计算
public class Solution {
/**
* @param costs: n x k cost matrix
* @return: an integer, the minimum cost to paint all houses
*/
public int minCostII(int[][] costs) {
int n = costs.length;
if(n == 0)
return 0;
int k = costs[0].length;
if(k == 0)
return 0;
//数组定义:dp[i][j] 表示的是 0 -> i - 1号房刷j种颜色的最小花费
int dp[][] = new int[n + 1][k];
int ans = Integer.MAX_VALUE;
/**
状态方程 dp[i][j] = min(dp[i - 1][0..k-1]) + cost[i - 1][j]
**/
for(int i = 1; i <= n; i++) {
int firMin = Integer.MAX_VALUE, secMin = Integer.MAX_VALUE;
int firIdx = 0, secIdx = 0;
//寻找最小值和次小值以及他们的下标
for(int j = 0; j < k; j++) {
if(dp[i - 1][j] < firMin) {
secMin = firMin;
secIdx = firIdx;
firMin = dp[i - 1][j];
firIdx = j;
} else if(dp[i - 1][j] < secMin) {
secMin = dp[i - 1][j];
secIdx = j;
}
}
for(int j = 0; j < k; j++) {
//因为相邻房屋不能涂相同颜色,所以当j等于最小值下标时要选择次小值
if(j != firIdx) {
dp[i][j] = firMin + costs[i - 1][j];
} else {
dp[i][j] = secMin + costs[i - 1][j];
}
}
}
for(int i = 0; i < k; i++) {
ans = Math.min(ans, dp[costs.length][i]);
}
return ans;
}
}