洛谷1169 [ZJOI2007] 棋盘制作
题意概述:给出由0 1构成的矩阵,求没有0 1 相邻的最大子矩阵的最大子正方形。
解题思路:设f[i][j]表示i j向上能到哪,l[i][j] r[i][j]表示向左/右,转移时分开计算矩形和正方形即可。
#include<cstring> #include<iostream> #include<cctype> #include<cstdio> #include<algorithm> using namespace std; inline int read() { register int X=0;register char ch=0;bool flag=0; for(;!isdigit(ch);ch=getchar()) if(ch=='-') flag=1; for(;isdigit(ch);ch=getchar()) X=(X<<3)+(X<<1)+ch-'0'; return (flag ? -X : X); } inline void write(int x) { if(x>9) write(x/10); putchar(x%10+'0'); } const int N=2001; int l[N][N],r[N][N],f[N][N],n,m,a[N][N],ans1=0,ans2=0; int min(const int x,const int y){return (x < y ? x : y);} int max(const int x,const int y){return (x < y ? y : x);} int main() { n=read(),m=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(),l[i][j]=r[i][j]=(j==0 ? 1000000000 : j),f[i][j]=1; for(int i=1;i<=n;i++) { for(int j=2;j<=m;j++) if(a[i][j] != a[i][j-1]) l[i][j]=l[i][j-1]; for(int j=m-1;j>=1;j--) if(a[i][j] != a[i][j+1]) r[i][j]=r[i][j+1]; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(i > 1 && a[i][j] != a[i-1][j]) l[i][j]=max(l[i][j],l[i-1][j]),r[i][j]=min(r[i][j],r[i-1][j]),f[i][j]=f[i-1][j]+1; int k=r[i][j]-l[i][j]+1,h=min(k,f[i][j]); ans1=max(ans1,k*f[i][j]); ans2=max(ans2,h*h); } write(ans2),putchar('\n'),write(ans1); }
忘开longlong,忘用逆元,忘删调试信息,瞬间爆炸