LintCode 553: Bomb Enemy

本文探讨了在二维网格中,使用一枚炸弹消灭最多敌军的算法策略。提供了三种解法,包括时间复杂度O(n^3)的逐行逐列计算、O(n^2)的四方向累加优化方案,以及待实现的深度优先搜索方法。
  1. Bomb Enemy

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.

Example
Example1

Input:
grid =[
“0E00”,
“E0WE”,
“0E00”
]
Output: 3
Explanation:
Placing a bomb at (1,1) kills 3 enemies
Example2

Input:
grid =[
“0E00”,
“EEWE”,
“0E00”
]
Output: 2
Explanation:
Placing a bomb at (0,0) or (0,3) or (2,0) or (2,3) kills 2 enemies
Notice
You can only put the bomb at an empty cell.

解法1:
参考自网上。时间复杂度O(n^3)。
对每个i,j, 如果i==0,或上面一个元素为W,则计算j列从当前行到nRow累计的Enemy数。
如下图所示,当i=0,j=1时,所计算的累计enemy数为2(因为列1有2个E)。但grid[0][1]不为0,所以将colCount[1]保存下来,当i=1,j=1的时候就可以用上了。注意这里如果不保留下来colCount[j],仅仅用一个colEnemy的话,对固定的i,每个j都会重新计算colEnemy,那样就会不准了,即i=0,j=1算好的colEnemy的值会被i=0,j=2计算的colEnemy替代。
而rowEnemy因为j本来就是从大到小迭代过来的,所以用一个rowEnemy就足够了。
[0 E 0 0]
[E 0 W E]
[0 E 0 0]
代码如下:

class Solution {
public:
    /**
     * @param grid: Given a 2D grid, each cell is either 'W', 'E' or '0'
     * @return: an integer, the maximum enemies you can kill using one bomb
     */
    int maxKilledEnemies(vector<vector<char>> &grid) {
        int nRow = grid.size();
        if (nRow == 0) return 0;
        int nCol = grid[0].size();
        int rowEnemies = 0;
        vector<int> colCounts(nCol, 0);
    //    int colEnemies = 0;
        
        int maxCount = 0;
        for (int i = 0; i < nRow; ++i) {
            for (int j = 0; j < nCol; ++j) {
                
                if (i == 0 || grid[i - 1][j] == 'W') {
                    colCounts[j] = 0;
                    colEnemies = 0;
                    for (int k = i; k < nRow && grid[k][j] != 'W'; ++k) {
                        if (grid[k][j] == 'E') {
                            colCounts[j]++;
  //                          colEnemies++;
                        }
                    }
                }

                if (j == 0 || grid[i][j - 1] == 'W') {
                    rowEnemies = 0; 
                    for (int k = j; k < nCol && grid[i][k] != 'W'; ++k) {
                        if (grid[i][k] == 'E') rowEnemies++;
                    }
                }

                if (grid[i][j] == '0') {
                    maxCount = max(maxCount, rowEnemies + colCounts[j]);
                 //   maxCount = max(maxCount, rowEnemies + colEnemies);
                }
            }
        }
        return maxCount;
    }
};

解法2:也是参考自网上。感觉非常牛。
从上下左右四个方向累加。复杂度只有O(n^2)。
代码如下:

int maxKilledEnemies(vector<vector<char>>& grid) {
        if (grid.empty() || grid[0].empty()) return 0;
        int m = grid.size(), n = grid[0].size(), res = 0;
        vector<vector<int>> v1(m, vector<int>(n, 0)), v2 = v1, v3 = v1, v4 = v1;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) { //up->down
                int t = (j == 0 || grid[i][j] == 'W') ? 0 : v1[i][j - 1];
                v1[i][j] = grid[i][j] == 'E' ? t + 1 : t;
            }
            for (int j = n - 1; j >= 0; --j) { //down->up
                int t = (j == n - 1 || grid[i][j] == 'W') ? 0 : v2[i][j + 1];
                v2[i][j] = grid[i][j] == 'E' ? t + 1 : t;
            }
        }
        for (int j = 0; j < n; ++j) {
            for (int i = 0; i < m; ++i) { //left->right
                int t = (i == 0 || grid[i][j] == 'W') ? 0 : v3[i - 1][j];
                v3[i][j] = grid[i][j] == 'E' ? t + 1 : t;
            }
            for (int i = m - 1; i >= 0; --i) { //right->left
                int t = (i == m - 1 || grid[i][j] == 'W') ? 0 : v4[i + 1][j];
                v4[i][j] = grid[i][j] == 'E' ? t + 1 : t;
            }
        }
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == '0') {
                    res = max(res, v1[i][j] + v2[i][j] + v3[i][j] + v4[i][j]);
                }
            }
        }
        return res;
    }

解法3:
这题应该也可以用DFS做,对每个0,上下左右4个DFS,直到遇到W。或者不用DFS,直接往4个方向搜也可。
但时间复杂度高。下次做。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值