考察:线性dp
这也能dp系列,完全没想到.
注意这道题是检查子矩阵,所以不用围绕主矩阵的对角线检查.
思路:
枚举子矩阵的左下角坐标,定义f[i][j]是以(i,j)为左下角坐标的最长对称边长.可以发现f[i][j]的最大边长最多为f[i-1][j+1]+1.三重循环枚举即可.
这题的原思路是枚举左下角+二分,因为没想到右上角与左下角的关系,所以考虑一个个检查,但这样挺麻烦的.
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 const int N = 1010; 5 int n,f[N][N];//求的是最大对称子矩阵的和 6 char mp[N][N]; 7 int main() 8 { 9 while(scanf("%d",&n)!=EOF&&n) 10 { 11 int ans = 0; 12 for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); 13 for(int i=1;i<=n;i++) 14 for(int j=1;j<=n;j++) 15 { 16 f[i][j] = 1; 17 if(i-1>0&&i-1<=n&&j+1>0&&n>=j+1) 18 { 19 int k = 0; 20 while(k<=f[i-1][j+1]&&mp[i-k][j]==mp[i][j+k]) k++; 21 f[i][j] = k; 22 } 23 ans = max(ans,f[i][j]); 24 } 25 printf("%d\n",ans); 26 } 27 return 0; 28 }