1. 程式人生 > >lintcode 516. 房屋染色 II

lintcode 516. 房屋染色 II

描述

這裡有n個房子在一列直線上,現在我們需要給房屋染色,共有k種顏色。每個房屋染不同的顏色費用也不同,你需要設計一種染色方案使得相鄰的房屋顏色不同,並且費用最小。

費用通過一個nxk 的矩陣給出,比如cost[0][0]表示房屋0染顏色0的費用,cost[1][2]表示房屋1染顏色2的費用。

所有費用都是正整數

樣例

costs = [[14,2,11],[11,14,5],[14,3,10]] return 10

房屋 0 顏色 1, 房屋 1 顏色 2, 房屋 2

 顏色 1, 2 + 5 + 3 = 10

挑戰

用O(nk)的時間複雜度解決。

 

因為想到染到最後一個房子的最小值,為染到前一個房子的不同顏色最小值 與最後一個房子的cost得出。所以想到dp。dp[i][j]代表結束在編號i,顏色k的最小值。求dp[i][j]是可以遍歷i-1房子的不同顏色,所以容易想到O(nk^2)解法。但觀察到染到i的不同顏色最小值只是基於,i-1的最小值 和 i-1的第二小值。所以只限用fi,si兩個下標分別記錄染到房子i-1時最小顏色,和第二小顏色就行了,時間複雜度O(nk)。

O(nk^2)solution。

public int minCostII(int[][] costs) {
        if(costs==null||costs.length==0) return 0;
        int n=costs.length,k=costs[0].length;
        int[][] dp=new int[n][k];
        for(int j=0;j<k;j++){
            dp[0][j]=costs[0][j];
        }
        for(int i=1;i<n;i++){
            for(int j=0;j<k;j++){
                dp[i][j]=Integer.MAX_VALUE;
                for(int c=0;c<k;c++){
                    if(c==j) continue;
                    dp[i][j]=Math.min(dp[i-1][c]+costs[i][j],dp[i][j]);    
                }
            }
        }
        int min=dp[n-1][0];
        for(int j=1;j<k;j++) min=Math.min(min,dp[n-1][j]);
        return min;
    }

 

O(nk) solution

public int minCostII(int[][] costs) {
        if(costs==null||costs.length==0) return 0;
        int n=costs.length,k=costs[0].length;
        int[][] dp=new int[n][k];
        int fi=-1,si=-1;
        for(int j=0;j<k;j++){
            dp[0][j]=costs[0][j];
            if(fi==-1){
                 fi=j;
            }else if(dp[0][j]<=dp[0][fi]){
                si=fi;
                fi=j;
            }else if(si==-1||dp[0][j]<dp[0][si]){
                si=j;
            }
        }
        for(int i=1;i<n;i++){
            //fi,si前一個下標,f,s當前下標
            int f=-1,s=-1;
            for(int j=0;j<k;j++){
                if(dp[i-1][fi]==dp[i-1][si]||j!=fi){
                    dp[i][j]=dp[i-1][fi]+costs[i][j];    
                }else{
                    dp[i][j]=dp[i-1][si]+costs[i][j];                    
                }
                if(f==-1){
                    f=j;
                }else if(dp[i][j]<=dp[i][f]){
                    s=f;
                    f=j;
                }else if(s==-1||dp[i][j]<dp[i][s]){
                    s=j;
                }    
            }
            fi=f;
            si=s;
        }
        return dp[n-1][fi];