序列型动态规划
- 序列型动态规划:…前i个…最小/方式数/可行性
- 在设计动态规划的过程中,发现需要知道前n-1栋房子的最优策略中,房子n-2的颜色
- 如果只用f[N-1],将无法区分
- 解决方法:记录下房子n-2的颜色
- 在房子N-2是红/蓝/绿色的情况下,油漆前n-1栋房子的最小花费
- 序列+状态
示例
/**
* 515. 房屋染色
* 这里有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.
*/
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) {
// write your code here
int n = costs.length;
if(n == 0){
return 0;
}
int m = costs[0].length;
if(m == 0){
return 0;
}
// 构建状态数组,确定状态f[i][j]表示前i栋楼颜色为j情况下最小代价
// 最后一步:f[i][j]可由前i-1栋且颜色不为j子问题
// 子问题:到达状态f[i-1][!j]最小的代价
int[][] f = new int[n+1][m];
// 初始状态也就是前0栋房子的染色代价都为0
f[0][0] = f[0][1] = f[0][2] = 0;
// 通过状态转移方程求1到n栋楼下3种涂色情况分别的最小代价
for(int i = 1; i <= n; i++){
for(int j = 0; j < m; j++){
f[i][j] = Integer.MAX_VALUE;
for(int k = 0; k < m; k++){
if(k == j){
continue;
}
if(f[i-1][k] + costs[i-1][j] < f[i][j]){
f[i][j] = f[i-1][k] + costs[i-1][j];
}
}
}
}
int res = f[n][0];
if(f[n][1] < res){
res = f[n][1];
}
if(f[n][2] < res){
res = f[n][2];
}
return res;
}
}