package com.fishercoder.solutions;

import java.util.PriorityQueue;

/**
 * 407. Trapping Rain Water II
 *
 * Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining.

 Note:
 Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000.

 Example:

 Given the following 3x6 height map:
 [
 [1,4,3,1,3,2],
 [3,2,1,3,2,4],
 [2,3,3,2,3,1]
 ]

 Return 4.

 The above image represents the elevation map [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] before the rain.

 After the rain, water are trapped between the blocks. The total volume of water trapped is 4.

 */
public class _407 {
    public static class Solution1 {
        /** Reference: https://discuss.leetcode.com/topic/60418/java-solution-using-priorityqueue */
        public class Cell {
            int row;
            int col;
            int height;

            public Cell(int row, int col, int height) {
                this.row = row;
                this.col = col;
                this.height = height;
            }
        }

        public int trapRainWater(int[][] heights) {
            if (heights == null || heights.length == 0 || heights[0].length == 0) {
                return 0;
            }

            PriorityQueue<Cell> queue = new PriorityQueue<>(1, (a, b) -> a.height - b.height);

            int m = heights.length;
            int n = heights[0].length;
            boolean[][] visited = new boolean[m][n];

            // Initially, add all the Cells which are on borders to the queue.
            for (int i = 0; i < m; i++) {
                visited[i][0] = true;
                visited[i][n - 1] = true;
                queue.offer(new Cell(i, 0, heights[i][0]));
                queue.offer(new Cell(i, n - 1, heights[i][n - 1]));
            }

            for (int i = 0; i < n; i++) {
                visited[0][i] = true;
                visited[m - 1][i] = true;
                queue.offer(new Cell(0, i, heights[0][i]));
                queue.offer(new Cell(m - 1, i, heights[m - 1][i]));
            }

            // from the borders, pick the shortest cell visited and check its neighbors:
            // if the neighbor is shorter, collect the water it can trap and update its height as its height plus the water trapped
            // add all its neighbors to the queue.
            int[][] dirs = new int[][] {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
            int res = 0;
            while (!queue.isEmpty()) {
                Cell cell = queue.poll();
                for (int[] dir : dirs) {
                    int row = cell.row + dir[0];
                    int col = cell.col + dir[1];
                    if (row >= 0 && row < m && col >= 0 && col < n && !visited[row][col]) {
                        visited[row][col] = true;
                        res += Math.max(0, cell.height - heights[row][col]);
                        queue.offer(new Cell(row, col, Math.max(heights[row][col], cell.height)));
                    }
                }
            }

            return res;
        }
    }
}

@@ -66,655 +66,8 @@
 e;%0A%0A
-/**%0A * 407. Trapping Rain Water II%0A *%0A * Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining.%0A%0A Note:%0A Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000.%0A%0A Example:%0A%0A Given the following 3x6 height map:%0A %5B%0A %5B1,4,3,1,3,2%5D,%0A %5B3,2,1,3,2,4%5D,%0A %5B2,3,3,2,3,1%5D%0A %5D%0A%0A Return 4.%0A%0A The above image represents the elevation map %5B%5B1,4,3,1,3,2%5D,%5B3,2,1,3,2,4%5D,%5B2,3,3,2,3,1%5D%5D before the rain.%0A%0A After the rain, water are trapped between the blocks. The total volume of water trapped is 4.%0A%0A */%0A
 publ
@@ -129,16 +129,27 @@
      /**
+%0A         *
  Referen
@@ -226,16 +226,25 @@
 ityqueue
+%0A        
  */%0A    
@@ -1838,17 +1838,16 @@
  int%5B%5D%5B%5D
- 
 %7B%7B-1, 0%7D

refactor 407