题目链接:http://hihocoder.com/problemset/problem/1664?sid=1255092
题目:
描述
给定一个NxM的01矩阵,小Hi希望从中找到一个01间隔的子方阵,并且方阵的边长越大越好。
例如对于
0100100 1000101 0101010 1010101 0101010
在右下角有一个4x4的01间隔方阵。
输入
第一行包含两个整数N和M。
以下N行M列包含一个NxM的01矩阵。
对于30%的数据,1 ≤ N, M ≤ 250
对于100%的数据,1 ≤ N, M ≤ 1000
输出
输出最大的01间隔方阵的边长。
样例输入
5 7 0100100 1000101 0101010 1010101 0101010
样例输出
4
题意:略。
题解:先把行和列预处理一下,就像最大子段和一样,不同+1,相同变为1。初始化每行每列第一个为1。如果不符合条件(即对角不同,和上或和左相同)此时重新计数为1;
符合条件的话。状态转移方程:t[i][j]=min(t[i-1][j-1]+1,min(d1[i][j],d2[i][j]));(符合给定的限制,弄出最小的)(好有意思的题目...哒哒哒)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define PI acos(-1.0) 5 #define INF 0x3f3f3f3f 6 #define FAST_IO ios::sync_with_stdio(false) 7 #define CLR(arr,val) memset(arr,val,sizeof(arr)) 8 9 const int N=1111; 10 typedef long long LL; 11 int d1[N][N],d2[N][N],t[N][N]; 12 char a[N][N]; 13 14 int main(){ 15 int n,m; 16 cin>>n>>m; 17 for(int i=1;i<=n;i++) 18 for(int j=1;j<=m;j++) 19 cin>>a[i][j]; 20 21 for(int i=1;i<=n;i++){ 22 t[i][1]=1;d1[i][1]=1; 23 for(int j=2;j<=m;j++){ 24 if(a[i][j]!=a[i][j-1]) d1[i][j]=d1[i][j-1]+1; 25 else d1[i][j]=1; 26 } 27 } 28 29 for(int i=1;i<=m;i++){ 30 d2[1][i]=1;t[1][i]=1; 31 for(int j=2;j<=n;j++){ 32 if(a[j][i]!=a[j-1][i]) d2[j][i]=d2[j-1][i]+1; 33 else d2[j][i]=1; 34 } 35 } 36 37 int ans=1; 38 for(int i=2;i<=n;i++){ 39 for(int j=2;j<=m;j++){ 40 if(a[i][j]!=a[i-1][j-1]||a[i][j]==a[i-1][j]||a[i][j]==a[i][j-1]) t[i][j]=1; 41 else{ 42 t[i][j]=min(t[i-1][j-1]+1,min(d1[i][j],d2[i][j])); 43 } 44 ans=max(ans,t[i][j]); 45 } 46 } 47 cout<<ans<<endl; 48 return 0; 49 }