题目读懂都需要点时间
和LeetCode第 221 题:最大正方形(C++)_zj-CSDN博客有点类似,但是如果以某个点为+的中心考虑dp的话,需要考虑上下左右四个方向上连续1的个数,然后取最小值,但是怎么dp才能涉及四个方向呢?
难道需要事先计算一个数组(NN4)记录四个方向上连续1的个数吗?这也太暴力了。。。
不过还是先写出来,虽然效率很差,但还是通过了:
class Solution {
public:
int orderOfLargestPlusSign(int N, vector<vector<int>>& mines) {
vector<vector<int>> grid(N, vector<int>(N, 1));
for(const auto &w : mines) grid[w[0]][w[1]] = 0;
vector<vector<int>> up(N, vector<int>(N, 0));//每个元素的上方连续1的个数
for(int i = 1; i < N; ++i){//up
for(int j = 0; j < N; ++j){
if(grid[i-1][j] == 1) up[i][j] = 1 + up[i-1][j];
}
}
vector<vector<int>> down(N, vector<int>(N, 0));//每个元素的下方连续1的个数
for(int i = N-2; i >= 0; --i){//行
for(int j = 0; j < N; ++j){//列
if(grid[i+1][j] == 1) down[i][j] = 1 + down[i+1][j];
}
}
vector<vector<int>> left(N, vector<int>(N, 0));//每个元素的左方连续1的个数
for(int i = 1; i < N; ++i){//列
for(int j = 0; j < N; ++j){//行
if(grid[j][i-1] == 1) left[j][i] = 1 + left[j][i-1];
}
}
vector<vector<int>> right(N, vector<int>(N, 0));//每个元素的右方连续1的个数
for(int i = N-2; i >= 0; --i){//列
for(int j = 0; j < N; ++j){//行
if(grid[j][i+1] == 1) right[j][i] = 1 + right[j][i+1];
}
}
int res = 0;
for(int i = 0; i < N; ++i){
for(int j = 0; j < N; ++j){
if(grid[i][j] != 0) res = max(res, min(up[i][j], min(down[i][j], min(left[i][j], right[i][j]))));
}
}
if(res == 0){//判断是否全为0
for(int i = 0; i < N; ++i){
for(int j = 0; j < N; ++j){
if(grid[i][j] != 0) return 1;
}
}
return 0;
}
return res+1;
}
};
不过之前不好dp的原因是上下左右不好一起考虑,但是可以dp上和左(左上往右下走),再dp下和右(右下往左上走)。
测试之后发现并不行,还是需要四个方向分别计算。。。
不过上述的代码倒是可以精简一下:
class Solution {
public:
int up[501][501] = {0};
int down[501][501] = {0};
int left[501][501] = {0};
int right[501][501] = {0};
int orderOfLargestPlusSign(int N, vector<vector<int>>& mines) {
if(mines.size() == 0 || mines[0].size() == 0) return (N+1)/2;
vector<vector<int>> grid(N, vector<int>(N, 1));
for(const auto &w : mines) grid[w[0]][w[1]] = 0;
int res = 0;
for(int i=0;i<N;i++){
for(int j =0;j<N;j++){
if(grid[i][j] == 1){
up[i][j] = i > 0 ? up[i-1][j] + 1 : 1;
left[i][j] = j > 0 ? left[i][j-1] + 1 : 1;
}
int x = N-1-i, y = N-1-j;
if(grid[x][y] == 1){
down[x][y] = x < N-1 ? down[x+1][y] + 1 : 1;
right[x][y] = y < N-1 ? right[x][y+1] + 1 : 1;
}
}
}
for(int i = 0; i < N; ++i){
for(int j = 0; j < N; ++j){
if(grid[i][j] != 0) res = max(res, min(up[i][j], min(down[i][j], min(left[i][j], right[i][j]))));
}
}
return res;
}
};