1 描述
这里有n个房子在一列直线上,现在我们需要给房屋染色,共有k种颜色。每个房屋染不同的颜色费用也不同,你希望每两个相邻的房屋颜色不同
费用通过一个nxk 的矩阵给出,比如cost[0][0]表示房屋0染颜色0的费用,cost[1][2]表示房屋1染颜色2的费用。找到油漆所有房子的最低成本。
所有费用都是正整数
2 样例
2.1 样例1
输入:
costs = [[14,2,11],[11,14,5],[14,3,10]]
输出: 10
说明:
三个屋子分别使用第1,2,1种颜色,总花费是10。
2.2 样例2
输入:
costs = [[5]]
输出: 5
说明:
只有一种颜色,一个房子,花费为5
2.3 挑战
用O(nk)的时间复杂度解决
3 题解
3.1 解题思路
3.1.1 时间复杂度NKK的方法
正常情况下,油漆前i栋房子并且房子i-1是颜色1,颜色2…颜色k的最小花费分别为f[i][0],f[i][1] … f[i][k-1]
f[i][0] = min{f[i - 1][1] + costs[i - 1][0], f[i - 1][2] + costs[i - 1][0], … ,f[i - 1][k - 1] + costs[i - 1][0]}
f[i][1] = min{f[i - 1][1] + costs[i - 1][1], f[i - 1][2] + costs[i - 1][1], … ,f[i - 1][k - 1] + costs[i - 1][1]}
…
f[i][k - 1] = min{f[i - 1][1] + costs[i - 1][k - 1], f[i - 1][2] + costs[i - 1][k - 1], … ,f[i - 1][k - 1] + costs[i - 1][k - 1]}
3.1.2 时间复杂度为NK的方法
时间复杂度缩减为NK的方法为首先先每次遍历第i - 1个房子的所有花费中的最小值和次最小值,如果当前的要染色和最小值的j值一致,则选择次最小值为最小值,如果不是则选择最小值作为当前染色的选项。
3.2 代码实现
- 采用动态规划的方法处理
- 时间复杂度为nk
- 需要处理costs为空或者为1的特殊情况,其他的可以按照正常的处理流程来处理
class Solution {
public:
/**
* @param costs: n x k cost matrix
* @return: an integer, the minimum cost to paint all houses
*/
int minCostII(vector<vector<int>> &costs) {
// write your code here
int m = costs.size();
if (m == 0) {
return 0;
}
if (m == 1) {
return costs[0][0];
}
int k = costs[0].size();
int min1, min2;
int id1 = 0, id2 = 0;
vector<vector<int>> dp(m + 1);
for (int i = 0; i <= m; i++) {
dp[i].resize(k);
}
for (int i = 0; i < k; i++) {
dp[0][i] = 0;
}
for (int i = 1; i <= m; i++) {
min1 = min2 = INT_MAX;
for (int j = 0; j < k; j++) {
if (dp[i - 1][j] < min1) {
min2 = min1;
id2 = id1;
min1 = dp[i - 1][j];
id1 = j;
} else {
if (dp[i - 1][j] < min2) {
min2 = dp[i - 1][j];
id2 = j;
}
}
}
for (int j = 0; j < k; j++) {
dp[i][j] = costs[i - 1][j];
if (j != id1) {
dp[i][j] += min1;
} else {
dp[i][j] += min2;
}
}
}
int res = INT_MAX;
for (int i = 0; i < k; i++) {
res = min(res, dp[m][i]);
}
return res;
}
};