http://acm.hdu.edu.cn/showproblem.php?pid=1838
其实原先不知道这题是DP 我都想不到DP去
想了想没思路 看了下题解 经典思路 :第n大的都是由第n-1大的推出来的
记录以a(i,j)为右下端所能构成的最大棋盘 若a[i-1][j]和a[i][j-1]都与它不同 而且a[i-1][j-1]与它相同 则dp[i][j] = min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1 之所以是最小 是因为它要保证能全部构成 如:
1011
0101
1010
0101
dp[4][4] 如果可以由dp[3][3]推的话 就错了 应该是由dp[3][4]推来
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 using namespace std; 7 #define N 2010 8 #define LL __int64 9 char s[N][N]; 10 int dp[N][N]; 11 int main() 12 { 13 int i,j,k,n,t; 14 scanf("%d",&t); 15 while(t--) 16 { 17 memset(dp,0,sizeof(dp)); 18 scanf("%d",&n); 19 for(i = 1 ;i <= n ;i++) 20 { 21 getchar(); 22 for(j = 1 ; j <= n ; j++) 23 { 24 scanf("%c",&s[i][j]); 25 dp[i][j] = 1; 26 } 27 } 28 int maxz=0; 29 for(i = 2 ; i <= n ; i++) 30 for(j = 2 ; j <= n ; j++) 31 { 32 if(s[i][j]!=s[i-1][j]&&s[i][j]!=s[i][j-1]&&s[i][j]==s[i-1][j-1]) 33 dp[i][j] = min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1; 34 if(s[i][j]=='1') 35 maxz = max(dp[i][j],maxz); 36 } 37 LL num=0; 38 for(i = 1; i <= n ; i++) 39 for(j = 1 ; j <= n ; j++) 40 if(s[i][j]=='1'&&dp[i][j]==maxz) 41 num++; 42 cout<<maxz<<" "<<num<<endl; 43 } 44 return 0; 45 }