LintCode 515. Paint House 序列型动态规划,渣渣学算法系列

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;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值