package com.interview.dynamic;

/**
 * Paint House 2
 * https://leetcode.com/problems/paint-house/
 * https://leetcode.com/problems/paint-house-ii/
 */
public class PaintHouse {

    public int minCostTopDownPainHouse1(int[][] costs) {
        if (costs.length == 0) {
            return 0;
        }
        int[][] dp = new int[costs.length][3];
        return minCostUtil(costs, 0, -1, dp);
    }

    private int minCostUtil(int[][] costs, int house, int prevColor, int[][] dp) {
        if (house == costs.length) {
            return 0;
        }
        int min = Integer.MAX_VALUE;
        for (int i = 0; i <= 2; i++) {
            if (i == prevColor) {
                continue;
            }
            int val;
            if (dp[house][i] != 0) {
                val = dp[house][i];
            } else {
                val = costs[house][i] + minCostUtil(costs, house + 1, i, dp);
                dp[house][i] = val;
            }
            min = Math.min(min, val);
        }
        return min;
    }

    public int minCostBottomUpPaintHouse2(int[][] costs) {
        if (costs.length == 0 || costs[0].length == 0) {
            return 0;
        }
        int[][] dp = new int[costs.length][costs[0].length];
        for (int i = 0; i < costs[0].length; i++) {
            dp[0][i] = costs[0][i];
        }

        for (int i = 1; i < costs.length; i++) {
            Pair p = findMinSecondMin(dp[i - 1]);
            for (int j = 0; j < costs[0].length; j++) {
                dp[i][j] = costs[i][j];
                if (j == p.minIndex) {
                    dp[i][j] += dp[i-1][p.secondMinIndex];
                } else {
                    dp[i][j] += dp[i-1][p.minIndex];
                }
            }
        }
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < dp[0].length; i++) {
            min = Math.min(min, dp[dp.length - 1][i]);
        }
        return min;
    }

    class Pair {
        int minIndex;
        int secondMinIndex;
    }

    private Pair findMinSecondMin(int[] input) {
        int minIndex;
        int secondMinIndex;
        if (input[0] < input[1]) {
            minIndex = 0;
            secondMinIndex = 1;
        } else {
            minIndex = 1;
            secondMinIndex = 0;
        }
        for (int i = 2; i < input.length; i++) {
            if (input[i] < input[minIndex]) {
                secondMinIndex = minIndex;
                minIndex = i;
            } else if (input[i] < input[secondMinIndex]) {
                secondMinIndex = i;
            }
        }
        Pair p = new Pair();
        p.minIndex = minIndex;
        p.secondMinIndex = secondMinIndex;
        return p;
    }

    public static void main(String args[]) {
        PaintHouse ph = new PaintHouse();
        int[][] input = {{1, 2, 1}, {1, 4, 5}, {2, 6, 1}, {3, 3, 2}};
        System.out.println(ph.minCostBottomUpPaintHouse2(input));
    }
}

@@ -43,18 +43,16 @@
 nt House
- 2
 %0A * http
@@ -209,16 +209,19 @@
 inHouse1
+or2
 (int%5B%5D%5B%5D
@@ -382,16 +382,19 @@
 , 0, -1,
+ 3,
  dp);%0A  
@@ -466,16 +466,23 @@
 evColor,
+ int k,
  int%5B%5D%5B%5D
@@ -621,19 +621,18 @@
 = 0; i %3C
-= 2
+ k
 ; i++) %7B
@@ -893,16 +893,19 @@
  + 1, i,
+ k,
  dp);%0A  

update paint house