题目:
http://cstest.scu.edu.cn/soj/problem.action?id=3329
题意:
现有n*m矩阵,求矩阵的最大矩形面积且该矩形只含0;
解题思路:
如何利用单调栈来解决这个问题?
先将A[][]的0变为1,1变为0
矩阵A[][],我们可以先来预处理每一行,第i行与第i-1行的关系如果
A[i][j]是1,则A[i][j] += A[i-1][j]; 且对于每一行可以等价于下图:
所以对于每一行我们都可以用单调栈来求每一个最小值的对应的左右区间(在这段区间内该值为最小),所以每一行的最大值可求,总体的最大值可求,总的复杂度O(n*m)
注意:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN0 1001
#define min(aa,bb) ((aa)<(bb)?(aa):(bb))
struct node{
int L,R;
//int num;
};
int A[MAXN0][MAXN0],sum[MAXN0][MAXN0];
int sk[MAXN0];
int N,M;
node no[MAXN0];
void pro(int row){
int top = 0;
sk[++top] = 1;
for(int j=2;j<=M;++j){
while(top&&A[row][j]<A[row][sk[top]]){
no[j].L = no[sk[top]].L;
int tmp0 = sk[top];
top--;
if(top>0){
no[sk[top]].R = no[tmp0].R;
}
}
sk[++top] = j;
}
if(top>0){
int tmp0 = sk[top];
top--;
while(top>0){
no[sk[top]].R = no[tmp0].R;
tmp0 = sk[top];
top--;
}
}
}
int solve(){
int ans = 0;
for(int i=1;i<=N;++i){
sum[i][0] = 0;
for(int j=1;j<=M;++j){
if(A[i][j]){
A[i][j]+=A[i-1][j];
}
no[j].L = no[j].R = j;
//sum[i][j] += sum[i][j-1];
// sum[i][j] = A[i][j];
}
///int top = 0;
pro(i);
for(int j=1;j<=M;++j){
int tmp0 = A[i][j]*(no[j].R - no[j].L+1);
if(ans<tmp0){
ans = tmp0;
}
}
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&N,&M);
for(int i=1;i<=N;++i){
for(int j=1;j<=M;++j){
scanf("%d",&A[i][j]);
if(A[i][j]==1){
A[i][j] = 0;
}
else {
A[i][j] = 1;
}
// sum[i][j] = 0;
}
}
for(int j=1;j<=M;++j){
A[0][j] = 0;
}
int ans = solve();
printf("%d\n",ans);
}
return 0;
}