这道题的唯一的难点是:二维转化成一维的时候:
/* 如果当前行 j 位仍然是1,那么height[j]++。否则height[j]更新为0 */
比如第一列上一行是 '.', 第二行第一列是 'X',那肯定无法形成矩形。
问题描述
有一个 n*m 的棋盘,棋盘上的每个点都是红的或绿的。
你需要找出一个面积最大的矩形区域,使得其中没有绿的格子。
输入格式
第一行 2 个正整数 n,m,描述棋盘尺寸。
接下来 n 行描述这个棋盘,每行 m 个字符,每个字符为 . 或 X,其中 . 表示这个位置是红色的,X 表示这个位置是绿色的。
输出格式
一行一个整数,表示最大面积。
样例输入
4 5
.....
XXXXX
.X...
.....
样例输出
6
样例解释
以第 3 行第 3 列的方格为左上角,第 4 行第 5 列的方格为右下角的矩形区域是全红的矩形中面积最大的。
数据范围
对于 30% 的数据,n,m<=100;
对于 60% 的数据,n,m<=400;
对于 85% 的数据,n,m<=1,000;
对于 100% 的数据,n,m<=1,500。
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
int getAnswerInRow (int n, int *height);
int getAnswer(int n, int m, string *matrix);
int getAnswer(int n, int m, string *matrix) {
/* 如果当前行 j 位仍然是1,那么height[j]++。否则height[j]更新为0 */
int maxrect = 0;
int *height = new int[m+2];
for(int i = 0; i < m+2; i++)
height[i] = 0;
for(int i = 0; i < n; i++){
for( int j = 0; j < m; j++){
if(matrix[i][j] == 'X')
height[j+1] = 0; /*因为下个函数从1开始*/
else
height[j+1]++;
}
maxrect = max(maxrect, getAnswerInRow(m,height));
}
return maxrect;
}
int getAnswerInRow (int n, int *height) {
int ans = 0;
stack< int > myStack;
/* push(0) 是第一个哨兵 */
myStack.push(0);
/* N+1 是最后一个哨兵 */
for(int i = 1; i <= n+1; ++i){
while ((height[myStack.top()] > height[i])) {
int nowHeight = height[myStack.top()];
myStack.pop();
ans = max(ans, nowHeight * (i - myStack.top() - 1));
/* 其实蛮不容易的QAQ,我这一句一直写错,后来重新看了一遍视频才写出来- - */
}
myStack.push(i);
}
return ans;
/* 请在这里设计你的算法,并将答案返回 */
}
int main() {
ios::sync_with_stdio(false); // 读入优化
int n, m;
cin >> n >> m;
string *matrix = new string[n]();
for (int i = 0; i < n; ++i)
cin >> matrix[i];
cout << getAnswer(n, m, matrix) << endl;
delete[] matrix;
return 0;
}