LintCode 515. Paint House
描述:
这里有n个房子在一列直线上,现在我们需要给房屋染色,分别有红色蓝色和绿色。每个房屋染不同的颜色费用也不同,你需要设计一种染色方案使得相邻的房屋颜色不同,并且费用最小,返回最小的费用。费用通过一个nx3 的矩阵给出,比如cost[0][0]表示房屋0染红色的费用,cost[1][2]表示房屋1染绿色的费用。
样例
样例 1:
输入: [[14,2,11],[11,14,5],[14,3,10]]
输出: 10
解释: 蓝 绿 蓝, 2 + 5 + 3 = 10
样例 2:
输入: [[1,2,3],[1,4,6]]
输出: 3
动态规划组成部分一:确定状态
- 最优策略是话费最小的策略
- 最后一步:最优策略中房子N-1一定染成了红,蓝,绿中的一种
- 但是相邻两栋房子不能染成一种颜色
- 所以如果最优策略中房子N-1是红色,房子N-2只能是蓝色或绿色
- 所以如果最优策略中房子N-1是蓝色,房子N-2只能是红色或绿色
- 所以如果最优策略中房子N-1是绿色,房子N-2只能是红色或蓝色
- 如果直接套用以前的思路,记录油漆前N栋房子的最小花费
- 根据套路,也需要记录油漆前N-1栋房子的最小花费
- 但是,前N-1栋房子的最小花费的最优策略中,不知道房子N-2是什么颜色,所以可能和房子N-1撞色
-
不知道房子N-2是什么颜色,就把它记录下来!
- 分别记录油漆前N-1栋房子并且房子N-2是红色,蓝色,绿色的最小花费
-
值得注意的是在序列型动态规划中,前n个指的是0,1,2…n-1
动态规划组成部分二:转移方程
- 设油漆前i栋房子并且房子i-1是红色,蓝色,绿色的最小花费分别为f[ i ][ 0 ],f[ i ][ 1 ],f[ i ][ 2 ]
- f[ i ][ 0 ] = min{ f[ i-1 ][ 1 ] + cost[ i-1 ][ 0 ] , f[ i-1 ][ 2 ] + cost[ i-1 ][ 0 ] }
- 其中f[ i ][ 0 ]表示:油漆前i栋房子,并且房子i-1是红色的最小花费
- f[ i-1 ][ 1 ] + cost[ i-1 ][ 0 ] 表示:油漆前i-1栋房子并且房子i-2是蓝色的最小花费,加上油漆房子i-1的最小花费
- f[ i-1 ][ 2 ] + cost[ i-1 ][ 0 ] 表示:油漆前i-1栋房子并且房子i-2是绿色的最小花费,加上油漆房子i-1的最小花费
- f[ i ][ 1 ] = min{ f[ i-1 ][ 0 ] + cost[ i-1 ][ 1 ] , f[ i-1 ][ 2 ] + cost[ i-1 ][ 1 ] }
- 其中f[ i ][ 1 ]表示:油漆前i栋房子,并且房子i-1是蓝色的最小花费
- f[ i-1 ][ 0 ] + cost[ i-1 ][ 1 ] 表示:油漆前i-1栋房子并且房子i-2是红色的最小花费,加上油漆房子i-1的最小花费
- f[ i-1 ][ 2 ] + cost[ i-1 ][ 1 ] 表示:油漆前i-1栋房子并且房子i-2是绿色的最小花费,加上油漆房子i-1的最小花费
- f[ i ][ 2 ] = min{ f[ i-1 ][ 0 ] + cost[ i-1 ][ 2 ] , f[ i-1 ][ 1 ] + cost[ i-1 ][ 2 ] }
- 其中f[ i ][ 2 ]表示:油漆前i栋房子,并且房子i-1是绿色的最小花费
- f[ i-1 ][ 0 ] + cost[ i-1 ][ 2 ] 表示:油漆前i-1栋房子并且房子i-2是红色的最小花费,加上油漆房子i-1的最小花费
- f[ i-1 ][ 1 ] + cost[ i-1 ][ 2 ] 表示:油漆前i-1栋房子并且房子i-2是蓝色的最小花费,加上油漆房子i-1的最小花费
- 序列型动态规划的初始条件 f[0][0] = f[0][1] = f[0][2] = 0 , 即不油漆任何房子的花费为0
- 本题无边界情况,因为i依靠i-1,而0已经被处理
- 初始化f[0][0],f[0][1],f[0][2]
- 计算f[1][0],f[1][1],f[1][2]
- 计算…
- 计算f[n][0],f[n][1],f[n][2]
- 答案是min{ f[ n ][ 0 ],f[ n ][ 1 ],f[ n ][ 2 ] }
- 时间复杂度O(N),空间复杂度O(N)
public class Solution {
/**
* @param costs: n x 3 cost matrix
* @return: An integer, the minimum cost to paint all houses
*/
public int minCost(int[][] costs) {
int n = costs.length;
if(n == 0)
return 0;
//n+1 , f[0] ...... f[n]
int [][] f = new int[n+1][3];
int i,j,k,res;
f[0][0] = f[0][1] = f[0][2] = 0;
for(i=1;i<=n;i++){
// j is the color of house i-1
for(j=0;j<3;j++){
f[i][j] = Integer.MAX_VALUE;
// k is the color of house i-2
for(k=0;k<3;k++){
//cant be the same color
if(j==k){
continue;
}
if(f[i-1][k] + costs[i-1][j] < f[i][j]){
f[i][j] = f[i-1][k] + costs[i-1][j];
}
}
}
}
res = f[n][0];
if(f[n][1]<res){
res = f[n][1];
}
if(f[n][2]<res){
res = f[n][2];
}
return res;
}
}