题目来源
题目描述
class Solution {
public:
int maxKilledEnemies(vector<vector<char>>& grid){
}
};
题目解析
- 最好在十字路口,这样可以往四个方向炸
- 每个炸弹可以往四个方向炸,我们可以先分析一个方向,然后举一反三。
- 即如果在一个空地放一个炸弹,最多向上能够炸死多少敌人
- 可以直接枚举,即向上枚举到碰到墙为止。但是时间复杂度太高了
坐标型动态规划
先分析一个方向
(1)确定状态
-
我们假设有敌人或者有墙的格子也能放炸弹
- 有敌人的格子:格子里的敌人能够被炸死,并继续向上爆炸
- 有墙的格子:炸弹不能炸死任何敌人
-
那么,在(i, j)格放一个炸弹,它向上能够炸死的敌人数是:
(i, j)
为空地:那么就是(i-1, j)
格向上能炸死的敌人数(i, j)
为敌人:(i-1, j)
格向上能炸死的敌人数 + 1(i, j)
为墙:0
-
子问题:
- 原问题:求
(i, j)
格放一个炸弹向上能炸死的敌人数 - 子问题:求
(i-1, j)
格放一个炸弹向上能炸死的敌人数
- 原问题:求
-
状态:up[i][j]表示
(i, j)
格放一个炸弹向上能炸死的地人数
(2)转移方程
(3)初始条件和边界情况
- 初始条件:第0行的up值和格子内容有关
- 如果
(0, j)
格不是敌人:up[0][j] = 0
- 如果
(0, j)
格是敌人:up[0][j] = 1
- 如果
(4) 计算顺序
- 从上到下,从左到右
四个方向
- up[i][j]表示如果
(0, j)
放一个炸弹向上最多可以炸死多少敌人 - 一共四个方向,可以类似的计算
down[i][j]、left[i][j]、right[i][j]
,注意计算顺序会改变 (i, j)
如果是空地,放一个炸弹最多炸死的敌人数是up[i][j] + down[i][j] + left[i][j] + right[i][j]
- 返回值:取最大值即可
- 时间复杂度和空间复杂度都是O(NM)
class Solution {
public:
int maxKilledEnemies(vector<vector<char>>& grid){
if(grid.empty() || grid[0].empty()){
return 0;
}
int M = grid.size(), N = grid[0].size(), res = 0;
std::vector<std::vector<int>> v1(M, std::vector<int>(N, 0)), v2 = v1, v3 = v1, v4 = v1;
for (int i = 0; i < M; ++i) {
for (int j = 0; j < N; ++j) {
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) {
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) {
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) {
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] == 'O'){
res = max(res, v1[i][j] + v2[i][j] + v3[i][j] + v4[i][j]);
}
}
}
return res;
}
};