题解:
step1:
对于图上所有的棋盘一定属于以下两种类型:
1.黑格行列奇偶性相同,白格不同
2.白格行列奇偶性相同,黑格不同
在输入的时候属于第一种情况的赋1,属于第二种情况的赋0
问题就转化成统计最大的1或0矩形和正方形
step2:
正方形:
g1[i][j]表示以(i,j)为右下角的全1正方形边长
g2[i][j]表示以(i,j)为右下角的全0正方形边长
g[i][j]=min(g[i-1][j-1],min(g[i-1][j],g[i][j-1]))+1
ans为所有g1[i][j],g2[i][j]的最大值
答案即为ans*ans
矩形:
f1[i][j]表示在(i,j)上面(包括(i,j))有几个与(i,j)颜色相同的点
f2[i][j]表示在(i,j)下面(包括(i,j))有几个与(i,j)颜色相同的点
f1[i][j]=(a[i][j]==a[i-1][j])*f1[i-1][j]+1;
f2[i][j]=(a[i][j]==a[i+1][j])*f2[i+1][j]+1;
然后枚举i,再枚举j,枚举j的过程中记录k,保证k…j的颜色相同
计算c1=min(f1[i][k…j]),c2=min(f2[i][k…j])
用(j-k+1)*(c1+c2-1)不断更新ans
疑问:
如果存在一个k’>k,而c1’+c2’>c1+c2,那(j-k’+1)(c1’+c2’-1)有可能大于(j-k+1)(c1+c2-1),那么ans就不是最优的了
通俗的理解就是:我们的矩形是先保证长最大,宽尽量大,如果有一个长较小,矩形面积却比我们的面积大的矩形,这种情况怎么处理?
其实,这样的情况会在之前或之后考虑,也就是i’大于i或i’小于i的时候,具体情况可以自己画图理解一下,我无法给出很严格的证明
标程:
#include<bits/stdc++.h>
using namespace std;
#define o [2003][2003]
int n,m,i,j,a o,f o,g1 o,g2 o,f1 o,f2 o,ans,c1,c2,k;
int main(){
cin>>n>>m;
for (i=1;i<=n;i++)
for (j=1;j<=m;j++){
scanf("%d",&a[i][j]);
a[i][j]^=(i^j)&1;
f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j];
if (a[i][j]) g1[i][j]=min(g1[i-1][j-1],min(g1[i-1][j],g1[i][j-1]))+1;
else g2[i][j]=min(g2[i-1][j-1],min(g2[i-1][j],g2[i][j-1]))+1;
ans=max(ans,max(g1[i][j],g2[i][j]));
f1[i][j]=(a[i][j]==a[i-1][j])*f1[i-1][j]+1;
}
cout<<ans*ans<<endl;
ans=0;
for (i=n;i>=1;i--)
for (j=1;j<=m;j++) f2[i][j]=(a[i][j]==a[i+1][j])*f2[i+1][j]+1;
for (i=1;i<=n;i++){
c1=f1[i][1],c2=f2[i][1];k=1;
for (j=1;j<=m;j++){
ans=max(ans,(j-k+1)*(c1+c2-1));
if (a[i][j]==a[i][j+1]) c1=min(c1,f1[i][j+1]),c2=min(c2,f2[i][j+1]);
else c1=f1[i][j+1],c2=f2[i][j+1],k=j+1;
}
}
cout<<ans;
}