package com.freetymekiyan.algorithms.level.medium;

/**
 * Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return the maximum
 * enemies you can kill using one bomb.
 * The bomb kills all the enemies in the same row and column from the planted point until it hits the wall since the
 * wall is too strong to be destroyed.
 * Note that you can only put the bomb at an empty cell.
 * <p>
 * Example:
 * For the given grid
 * <p>
 * | 0 E 0 0
 * | E 0 W E
 * | 0 E 0 0
 * <p>
 * return 3. (Placing a bomb at (1,1) kills 3 enemies)
 * <p>
 * Company Tags: Google
 * Tags: Dynamic Programming
 */
public class BombEnemy {

    public static final char WALL = 'W';
    public static final char ENEMY = 'E';
    public static final char EMPTY = '0';

    /**
     * DP.
     * Not exactly the same idea as general DP.
     * Just avoid duplicate searching for number of enemies each row and each column.
     * For each cell from left to right at each row:
     * | Use an integer rowHits to store the # of enemies can hit at this row.
     * | Only update rowHits when first column(j==0) or there is a wall at the left cell(grid[i][j-1] == 'W').
     * | Use an integer array colHits[] to store the # of enemies can hit at this column.
     * | Only update colHits when i == 0 or grid[i - 1][j] == 'W'.
     * | If grid[i][j] is empty:
     * |   Update result. result = max(result, rowHits + colHits[j]).
     * Return max.
     */
    public int maxKilledEnemies(char[][] grid) {
        if (grid == null) {
            return 0;
        }
        int m = grid.length;
        int n = m == 0 ? 0 : grid[0].length;
        int max = 0;
        int rowHits = 0;
        int[] colHits = new int[n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == WALL) { // Note that WALL cell can be skipped.
                    continue;
                }
                if (j == 0 || grid[i][j - 1] == WALL) {
                    rowHits = 0;
                    for (int k = j; k < n && grid[i][k] != WALL; k++) {
                        if (grid[i][k] == ENEMY) {
                            rowHits++;
                        }
                    }
                }
                if (i == 0 || grid[i - 1][j] == WALL) {
                    colHits[j] = 0;
                    for (int k = i; k < m && grid[k][j] != WALL; k++) {
                        if (grid[k][j] == ENEMY) {
                            colHits[j]++;
                        }
                    }
                }
                if (grid[i][j] == EMPTY) { // Only update when the cell is empty.
                    max = (rowHits + colHits[j]) > max ? rowHits + colHits[j] : max;
                }
            }
        }
        return max;
    }
}

add bomb enemy