基准时间限制:1 秒 空间限制:131072 KB 分值: 80
难度:5级算法题
给出1个M*N的矩阵M1,里面的元素只有0或1,找出M1的一个子矩阵M2,M2中的元素只有1,并且M2的面积是最大的。输出M2的面积。
Input
第1行:2个数m,n中间用空格分隔(2 <= m,n <= 500) 第2 - N + 1行:每行m个数,中间用空格分隔,均为0或1。
Output
输出最大全是1的子矩阵的面积。
Input示例
3 3 1 1 0 1 1 1 0 1 1
Output示例
4
求出每个位置向右延伸,连续1的最大值,图中的矩阵就变为
1 2 0
1 2 3
0 1 2
然后用单调栈求出每个位置,对应的行最长区间,使该位置在这区间上是最小值
#include <bits/stdc++.h>
#define maxn 505
using namespace std;
int num[maxn][maxn], p[maxn][maxn];
int Left[maxn][maxn], Right[maxn][maxn];
int Stack[maxn];
int main(){
//freopen("in.txt", "r", stdin);
int m, n;
scanf("%d%d", &m, &n);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d", &num[i][j]);
for(int i = 0; i < n; i++){
int h = m;
for(int j = m-1; j >= 0; j--){
if(num[i][j] == 0)
h = j;
else{
p[i][j] = h - j;
}
}
}
for(int j = 0; j < m; j++){
int e = 0;
for(int i = 0; i < n; i++){
if(p[i][j] == 0){
e = 1;
Stack[0] = i;
}
else{
while(e && p[i][j] <= p[Stack[e-1]][j])
e--;
if(e)
Left[i][j] = i - Stack[e-1];
else
Left[i][j] = i + 1;
Stack[e++] = i;
}
}
}
for(int j = 0; j < m; j++){
int e = 0;
for(int i = n-1; i >= 0; i--){
if(p[i][j] == 0){
e = 1;
Stack[0] = i;
}
else{
while(e && p[i][j] <= p[Stack[e-1]][j])
e--;
if(e)
Right[i][j] = Stack[e-1] - i;
else
Right[i][j] = n - i;
Stack[e++] = i;
}
}
}
int ans = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
if(p[i][j]){
ans = max(ans, p[i][j] * (Right[i][j] + Left[i][j] - 1));
}
}
printf("%d\n", ans);
return 0;
}