一、最大子矩阵问题
考虑这样一个问题,对于一个n*m的01矩阵,找出其中面积(或者周长)最大的全0或者全1子矩阵
王知昆在《浅谈用极大化思想解决最大子矩形问题》中给出两种方法。
【论文地址】http://wenku.baidu.com/view/0d787294dd88d0d233d46a96.html
【例题】
hdu1505 http://acm.hdu.edu.cn/showproblem.php?pid=1505
给定一个n*m的矩阵,矩阵用R表示这个格子不可用,F表示可用。求面积最大的全F矩阵,要求输出最大矩阵面积*3。
测试数据比较坑,没有按照规定格式,有很多冗余空格,注意用printf("%s")除去多余空格。
下面程序用的是悬线法。
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int MAXN=1001;
int T,n,m,ans;
int g[MAXN][MAXN],h[MAXN][MAXN],l[MAXN][MAXN],r[MAXN][MAXN];
char ch[1];
void work_line()
{
int ll,rr,len;
for(int i=1;i<=n;i++)
{
ll=0;
for(int j=1;j<=m;j++)
{
if(g[i][j]==1) ll=j;
l[i][j]=ll;
}
rr=m+1;
for(int j=m;j>=1;j--)
{
if(g[i][j]==1) rr=j;
r[i][j]=rr;
}
}
ans=0;
for(int j=1;j<=m;j++)
{
if(g[1][j]==1)
{
h[1][j]=0;
continue;
}
else
{
h[1][j]=1;
}
len=r[1][j]-l[1][j]-1;
if(len*h[1][j]>ans)
ans=len*h[1][j];
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(g[i][j]==1)
{
h[i][j]=0;
continue;
}
else
{
h[i][j]=h[i-1][j]+1;
if(g[i-1][j]==0)
{
l[i][j]=max(l[i-1][j],l[i][j]);
r[i][j]=min(r[i-1][j],r[i][j]);
}
len=r[i][j]-l[i][j]-1;
if(len*h[i][j]>ans)
ans=len*h[i][j];
}
}
}
}
void work_output()
{
printf("%d\n",ans*3);
}
void work_input()
{
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("%s",ch);
if(ch[0]=='R') g[i][j]=1;
else g[i][j]=0;
}
}
work_line();
work_output();
}
}
int main()
{
work_input();
return 0;
}