题目大意:
26个字母组成的n*n的矩阵,找出最大子矩阵关于左下到右上对角线对称的最大阶数。
思路:
(i,j)表示 i 行 j 列
dp[i][j] 表示(i,j)为矩阵左小角满足条件的最大子矩阵的阶数
显然若dp[i][j] = k, dp[i+1][j-1] = k - 1,反之,若dp[i + 1][j - 1] 为k,增加一阶使左下角为(i,j),则需要判断新增加的两条边对应是否相同就可知道dp[i][j]的大小。
故状态又dp[i - 1][j + 1]转移到dp[i][j]
转移方程详见代码
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1010;
int n;
char mp[maxn][maxn];
int d[maxn][maxn];
int dp(int x, int y)
{
if(x == 0 || y == n - 1) return d[x][y] = 1;
if(d[x][y]) return d[x][y];
int temp = dp(x - 1, y + 1);
d[x][y] = 1; //肯定与自身对称
for(int i = 1; i <= temp; i++)
{
if(x - i < 0 || y + i >= n) break;
else
{
if(mp[x - i][y] == mp[x][y + i]) d[x][y] = i + 1; //有几个相同,就多几阶对称
else break;
}
}
return d[x][y];
}
int main()
{
while(scanf("%d",&n) && n)
{
memset(mp,0,sizeof(mp));
for(int i = 0; i < n; i++)
{
scanf("%s",mp[i]);
}
memset(d, 0, sizeof(d));
int ans = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
d[i][j] = dp(i,j);
ans = max(ans, d[i][j]);
}
printf("%d\n",ans);
}
}