基准时间限制: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
然后发现对于每一列来说,要求的是一个区间内的最小值乘以区间长度,所有这些值的最大值。这就是对一个元素的两边进行扩展,发现这就是单调栈的应用了。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
int res;
int m, n;
int lef[505], sta[505];
int row[505][505];
int val[505][505];
void input()
{
int i, j;
res = 0;
scanf("%d%d", &m, &n);
for (i = 1; i <= m; i++)
{
for (j = 1; j <= n; j++)
{
scanf("%d", &val[i][j]);
if (val[i][j])
{
val[i][j] = val[i][j - 1] + 1;
res = max(res, val[i][j]);
}
}
}
}
void solve()
{
int i, j, k;
res = 0;
for (j = 1; j <= n; j++)
{
int top = 0;
val[m + 1][j] = -1;
for (i = 1; i <= m + 1; i++)
{
if (top == 0 || val[i][j] > val[sta[top - 1]][j])
{
sta[top++] = i;
lef[i] = i;
continue;
}
if (val[i][j] == val[sta[top - 1]][j])
{
continue;
}
while (top >= 1 && val[i][j] < val[sta[top - 1]][j])
{
--top;
int tmp = (i - lef[sta[top]])*val[sta[top]][j];
res = max(res, tmp);
}
lef[i] = lef[sta[top]];
sta[top++] = i;
}
}
cout << res << endl;
}
int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout);
input();
solve();
//system("pause");
return 0;
}