洛谷 P1169||bzoj1057 [ZJOI2007]棋盘制作
这个题目跟最大全0子矩阵是类似的。正方形的话,只要把任意极大子正方形(”极大“定义见后面的”论文“)当成把某个极大子矩形去掉一块变成正方形即可,容易解决。
解法1:看论文里面的“算法2“(那个是最大全0子矩阵方法,改一下就可以用在此题)
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 typedef pair<int,int> pii; 13 int n,m; 14 int a[2010][2010]; 15 int lp[2010][2010],rp[2010][2010]; 16 int lx[2010][2010],rx[2010][2010]; 17 int hei[2010][2010]; 18 int an1,an2; 19 int calc(int x,int y) 20 { 21 return min(x,y)*min(x,y); 22 } 23 int main() 24 { 25 int i,j; 26 scanf("%d%d",&n,&m); 27 for(i=1;i<=n;++i) 28 { 29 for(j=1;j<=m;++j) 30 { 31 scanf("%d",&a[i][j]); 32 } 33 } 34 for(i=1;i<=n;++i) 35 { 36 lx[i][1]=1; 37 for(j=2;j<=m;++j) 38 lx[i][j]=(a[i][j]==a[i][j-1])?j:lx[i][j-1]; 39 rx[i][m]=m; 40 for(j=m-1;j>=1;--j) 41 rx[i][j]=(a[i][j]==a[i][j+1])?j:rx[i][j+1]; 42 } 43 for(i=1;i<=n;++i) 44 { 45 for(j=1;j<=m;++j) 46 { 47 if(i!=1&&a[i][j]!=a[i-1][j]) 48 { 49 hei[i][j]=hei[i-1][j]+1; 50 lp[i][j]=max(lp[i-1][j],lx[i][j]); 51 rp[i][j]=min(rp[i-1][j],rx[i][j]); 52 } 53 else 54 { 55 hei[i][j]=1; 56 lp[i][j]=lx[i][j]; 57 rp[i][j]=rx[i][j]; 58 } 59 //printf("1t%d %d %d %d %d\n",i,j,hei[i][j],lp[i][j],rp[i][j]); 60 an1=max(an1,hei[i][j]*(rp[i][j]-lp[i][j]+1)); 61 an2=max(an2,calc(hei[i][j],rp[i][j]-lp[i][j]+1)); 62 } 63 } 64 printf("%d\n",an2); 65 printf("%d\n",an1); 66 return 0; 67 }
解法2:
其实最大全0子矩阵还有一种做法:
枚举每一行作为子矩阵的下底部,求出每一列向上最多扩展几行,然后直接用lightoj1083的做法求解此时的最大子矩阵,取所有方案最大值即可
改一下也可以用在此题
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 typedef pair<int,int> pii; 13 int st[2010],r[2010],l[2010],len; 14 int an1,an2; 15 int n,m; 16 int calc(int x,int y) 17 { 18 return min(x,y)*min(x,y); 19 } 20 void solve(int *d,int m) 21 { 22 int i; 23 len=0; 24 for(i=1;i<=m;++i) 25 { 26 while(len>0&&d[st[len]]>=d[i]) r[st[len--]]=i-1; 27 l[i]=st[len]; 28 st[++len]=i; 29 } 30 while(len>0) r[st[len--]]=m; 31 for(i=1;i<=m;++i) 32 { 33 an1=max(an1,d[i]*(r[i]-l[i])); 34 an2=max(an2,calc(d[i],r[i]-l[i])); 35 } 36 } 37 int a[2010][2010],hei[2010][2010]; 38 int main() 39 { 40 int i,j,k; 41 scanf("%d%d",&n,&m); 42 for(i=1;i<=n;++i) 43 { 44 for(j=1;j<=m;++j) 45 { 46 scanf("%d",&a[i][j]); 47 hei[i][j]=(i==1||a[i][j]==a[i-1][j])?1:hei[i-1][j]+1; 48 } 49 } 50 for(i=1;i<=n;++i) 51 { 52 for(j=1;j<=m;j=k+1) 53 { 54 k=j; 55 while(k+1<=m&&a[i][k+1]!=a[i][k]) ++k; 56 //printf("1t%d %d %d\n",i,j,k); 57 solve(hei[i]+j-1,k-j+1); 58 } 59 } 60 printf("%d\n",an2); 61 printf("%d\n",an1); 62 return 0; 63 }