直接搜肯定过不去,后来看到题解别人按他的思路搜索无剪枝也能过,试了下结果还是不行,不过思路倒是不错,每个点若2x2满足
要看3x3只用看额外加入的一行一列。
官方题解好像是dp,状态方程 dp[i][j]=min(dp[i+1][j],dp[i][j+1],dp[i+1][j+1])+1;
G[i+1][j] , G[i][j+1] , G[i+1][j+1]分别为(i,j)向下、向右、向右下一格的状况。 在(n-1,n-1)当且仅当三者都为1的时候,正方形才能扩充。从最右下向上,依次扩充即可
按照这个思路写了个
1 /* 2 3 ID: hubiao cave 4 5 PROG: range 6 7 LANG: C++ 8 9 */ 10 11 12 13 14 #include<iostream> 15 16 #include<fstream> 17 18 #include<string> 19 20 using namespace std; 21 22 23 int min3(int,int,int); 24 int farm[252][252]; 25 int f[252]; 26 int num; 27 int counter(int); 28 int main() 29 30 { 31 32 ifstream fin("range.in"); 33 ofstream fout("range.out"); 34 35 fin>>num; 36 for(int i=0;i<num;i++) 37 for(int j=0;j<num;j++) 38 { 39 char ch; 40 fin>>ch; 41 farm[i][j]=ch-'0'; 42 } 43 44 for(int i=num-2;i>=0;i--) 45 for(int j=num-2;j>=0;j--) 46 { 47 if(farm[i][j]) 48 farm[i][j]=min3(farm[i+1][j],farm[i][j+1],farm[i+1][j+1])+1; 49 if(farm[i][j]>1) 50 for(int m=2;m<=farm[i][j];m++) 51 f[m]++; 52 53 } 54 for(int i=2;i<=num;i++) 55 { 56 if(f[i]>0) 57 fout<<i<<" "<<f[i]<<endl; 58 59 } 60 61 62 63 return 0; 64 65 66 } 67 68 int counter(int r) 69 { 70 int t=0; 71 for(int i=0;i<num-r+1;i++) 72 for(int j=0;j<num-r+1;j++) 73 { 74 if(farm[i][j]!=1) 75 continue; 76 int ti=i; 77 int tj=j; 78 79 while(max(ti,tj)+1<num&&farm[ti+1][tj+1]) 80 { 81 tj++,ti++; 82 int flag=false; 83 for(int m=j;m<=tj;m++) 84 if(!farm[ti][m]) 85 { 86 flag=true; 87 break; 88 } 89 if(!flag) 90 { 91 for(int m=i;m<=ti;m++) 92 if(!farm[m][tj]) 93 { 94 flag=true; 95 break; 96 } 97 } 98 else 99 break; 100 if(flag) 101 break; 102 else 103 f[ti-i+1]++; 104 } 105 } 106 return 0; 107 } 108 109 int min3(int a,int b,int c) 110 { 111 return min(c,min(a,b)); 112 }