256 Paint House

There are a row of n houses, each house can be painted with one of the three colors: red, blue or green. The cost of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent houses have the same color.

The cost of painting each house with a certain color is represented by a n x 3 cost matrix. For example, costs[0][0] is the cost of painting house 0 with color red; costs[1][2] is the cost of painting house 1 with color green, and so on... Find the minimum cost to paint all houses.

Note: All costs are positive integers.


分析

输入:一个能代表花费的二维数组cost[][]

输出:最小花费 int minCost

思路1:recursion

1.定义递归函数:OPT()

第一个限制:总花费最小---》id:从0到id的房子

第二个限制:相邻不能同色---》color:第id个房子涂color色

OPT(id, color):0至第id个房子且第id个房子涂color色时最低的花费

2.递归公式:

OPT(id, 0) = min{ OPT(id-1,1) + cost[id][0], OPT(id-1,2) + cost[id][0]}

OPT(id, 1) = min{ OPT(id-1,0) + cost[id][0], OPT(id-1,2) + cost[id][0]}

OPT(id, 2) = min{ OPT(id-1,0) + cost[id][0], OPT(id-1,1) + cost[id][0]}

3.输出

minCost = min{OPT(n-1, 0), OPT(n-1, 1), OPT(n-1, 2)}

其中n是房子的数量

思路1实现中遇到的问题

1.递归函数minCostHelper(int id, int color)的定义

由于递归函数中需要用到cost[][],因此考虑要不要把cost当作递归函数一个参数传进去。其实可以更简便的方法是,设一对于class的instance variable,在主方法中进行赋值,因此递归函数也可以用。

2.递归函数中如何设计根据color的值来得出另两个

1)取余运算:(color+1)%3 与(color-1)%3

但是在实现中会ava.lang.StackOverflowError(有待解决)

2)if语句简单粗暴

3.如何比较3个数的大小

1)if语句简单粗暴

    //return min{x,y,z};
    if(x <= y && x <= z) return x;
    if(y <= x && y <= z) return y;
    return z;

注意:一定要是<=而不是<,这样要是x=y<z时,结果才能正确!!!

思路1代码

public class Solution {

    private int[][] costs;

    public int minCost(int[][] costs) {

    this.costs = costs;
    int n = costs.length;

    if(n == 0) return 0;

    int x = minCostHelper(n-1,0);
    int y = minCostHelper(n-1,1);
    int z = minCostHelper(n-1,2);

    //return min{x,y,z};
    if(x <= y && x <= z) return x;
    if(y <= x && y <= z) return y;
    return z;


    }

    private int minCostHelper(int id, int color) {

    int min = 0;
    //base case
    if(id == 0 && color == 0) return min = costs[0][0];
    if(id == 0 && color == 1) return min = costs[0][1];
    if(id == 0 && color == 2) return min = costs[0][2];

    int m,n;
    //recursive
    if(color == 0) {
        m = 1;
        n = 2;
    }else if(color == 1) {
        m = 0;
        n = 2;
    }else {
        m = 0;
        n = 1;
    }
    int a = minCostHelper(id-1,m) + costs[id][color];
    int b = minCostHelper(id-1,n) + costs[id][color];

    if( a < b ) min = a;
    else min = b;

    return min;
    }
}

思路1结果:Time limit Exceeded

原因是只采用了递归,相当于是从树的root往下计算,每条支路的每一个节点都会重新计算,因此不同支路的计算中会进行多次重复计算,运算复杂O(n^2)--Exponential!

思路2: 对递归进行修改,增加Memo[ ][ ]——DP

此时运用递归函数从Memo[ ][ ]的低端开始计算,之后的Memo值用之前已经计算的值(如果有的话),如果没有,用递归函数算。

//主方法
for i from 0 to n-1:
    Memo[i][0] = minCostHelper(i, 0);
    Memo[i][1] = minCostHelper(i, 1);
    Memo[i][1] = minCostHelper(i, 1);
endfor

minCost = min{Memo[n-1][0],Memo[n-1][1],Memo[n-1][2]}
//递归函数
    //base case
    if i==0 and color==0/1/2:
        Memo[0][0/1/2] = cost[0][0/1/2];
    endif

    //recursive
    if Memo[id][color] == 0:
        Memo[id][color] = min{Memo[id-1][color1] + cost[id][color], Memo[id-1][~color2] + cost[id][color]};
        return Memo[id][color]
    else:
        return Memo[id][color];

思路2实现中的问题

1.Memo[][]怎么建,在哪建

设一个instance variable的索引让递归函数能用,在主方法中根据cost的长度对索引赋值。

AC CODE

//jiayuanh_0201: 3 ms, Your runtime beats 12.86% of java submissions.
public class Solution {

    private int[][] costs;
    private int[][] Memo;

    public int minCost(int[][] costs) {

        this.costs = costs;
        int n = costs.length;
        this.Memo = new int[n][3];

        //corner case
        if(n == 0) return 0;

        //general case
        for(int i=0; i<n; i++) {

            Memo[i][0] = minCostHelper(i,0);
            Memo[i][1] = minCostHelper(i,1);
            Memo[i][2] = minCostHelper(i,2);

        }

        if((Memo[n-1][0] <= Memo[n-1][1]) && (Memo[n-1][0] <= Memo[n-1][2])) {
            return Memo[n-1][0];
        } else if ((Memo[n-1][1] <= Memo[n-1][0]) && (Memo[n-1][1] <= Memo[n-1][2])) {
            return Memo[n-1][1];
        } else {
            return Memo[n-1][2];
        }
    }

    private int minCostHelper(int id, int color) {

        int min = 0;
        //base case
        if(id == 0 && color == 0) {
            Memo[0][0] = costs[0][0];
            return Memo[0][0];
        }
        if(id == 0 && color == 1) {
            Memo[0][1] = costs[0][1];
            return Memo[0][1];
        }
        if(id == 0 && color == 2) {
            Memo[0][2] = costs[0][2];
            return Memo[0][2];
        }

        //recursive
        if(Memo[id][color] == 0) {
            int m,n;
            if(color == 0) {
            m = 1;
            n = 2;
            } else if(color == 1) {
            m = 0;
            n = 2;
            } else {
            m = 0;
            n = 1;
            }

            int a = minCostHelper(id-1,m) + costs[id][color];
            int b = minCostHelper(id-1,n) + costs[id][color];

            if( a < b ) {
            Memo[id][color] = a;
            }
            else {
            Memo[id][color] = b;
            }
            return Memo[id][color];
        } else {
            return Memo[id][color];
        } 

    }
}

results matching ""

    No results matching ""