Once upon a time there lived an old wise king. He had only one son. The prince had the idea that he (the prince) was about to be the future king; that's why he became too lazy day by day. This made the wise king a bit worried because his lazy son couldn't be the correct man for the throne. He couldn't sleep; his kingdom was in need of a perfect king, not the lazy king.
One day, while doing his regular works, he found an excellent idea. Next day he called his son. He said that he wanted the prince to have his own kingdom. The prince became very excited. The king continued that the prince can have a land from the king's kingdom, but he should start walking after sunrise and cover a rectangular area before sunset. Then the land would be given to the prince. The lazy prince thought, "It would be an easy task!" That's why he wanted to find the maximum rectangular area in king's land. But there were some rocks in the kingdom, and the prince didn't want any rocks in his new land. He would rather take nothing, but no rocks.
The kingdom can be thought as an m x n grid, where m is the number of rows and n is the number of columns. Each cell in the grid is a small rectangular land whose area is one. If a land contains rock it will be denoted by a 1, otherwise it will be denoted by a 0. The prince can walk in the sides of the cells and he can either take a cell (land) or ignore it, but he can't take a part of a cell. Now your task is to find the maximum rectangular area the prince could cover.
Input
Input starts with an integer T (≤ 4), denoting the number of test cases.
Each case starts with a line containing two integers: m and n (1 ≤ m, n ≤ 2000). Each of the next m lines contains n characters (either 0 or 1) denoting the kingdom.
Output
For each case, print the case number and the maximum rectangular area the prince could take.
Sample Input |
Output for Sample Input |
|
2 5 7 0110110 0000010 1000001 0100001 1100010 3 3 001 100 101 |
Case 1: 12 Case 2: 3 |
题目就是让你求在一个n*m的矩阵里找出一个全是0的子矩阵,要求子矩阵的面积最大,求最大的面积。
我们可以把矩阵处理一下,对于第二个样例吧
3 3
001
100
101
可以把到每个位置有连续多少个0先处理出来,就得到这样一个矩阵
120
012
010
这样我们就会发现,每一个子矩阵的面积就是对于每一列来说,一个区间内的最小值乘以区间的长度,因为每一列上的数值就代表这个矩阵的长,区间长度就相当于这个矩阵的宽。
到这里,就能联系上单调栈了,可以用单调栈快速的求出区间的最小值乘以区间的长度。
我们就以栈底为较小的元素的单调栈举例吧。(这样能求出以某个元素为最小值的一系列的最优解)
当栈为空的时候,肯定要把第一个元素放进栈里,然后到第二个元素的时候,因为要求是以某个数为最小值,所以如果栈顶元素比当前元素要大,就要弹出,直到栈顶元素小于当前元素,这样就能求出这个元素向左能延伸到哪,当某个元素被从栈里弹出的时候,也就知道这个被弹出的元素向右能延伸到哪。最后还在栈里的元素,肯定向右都能延伸到最后一个位置。
这样,以每一个元素为最小的区间长度都求出来了,就可以很轻松的求出所要的答案。
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
char t[2200][2200];
int a[2200][2200];
struct node
{
int l,i,r;
}p[2200];
stack<node> s;
int main(void)
{
int T,n,m,i,j;
scanf("%d",&T);
int cas = 1;
while(T--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%s",t[i]+1);
memset(a,0,sizeof(a));
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(t[i][j] == '0')
a[i][j] = a[i][j-1] + 1;
}
}
int ans = 0;
for(j=1;j<=m;j++)
{
for(i=1;i<=n;i++)
{
p[i].i = i;
p[i].l = i;
while(!s.empty() && a[s.top().i][j] > a[i][j])
{
p[i].l = s.top().l;
p[s.top().i].r = i - 1;
s.pop();
}
s.push(p[i]);
}
while(!s.empty())
{
p[s.top().i].r = n;
s.pop();
}
for(i=1;i<=n;i++)
{
ans = max(ans,(p[i].r - p[i].l + 1)*a[p[i].i][j]);
}
}
printf("Case %d: %d\n",cas++,ans);
}
return 0;
}

本文介绍了一种算法,用于寻找给定矩阵中全为0的最大子矩阵面积。通过预处理和使用单调栈优化,该算法能够高效地解决此问题。
2241

被折叠的 条评论
为什么被折叠?



