http://acm.hdu.edu.cn/showproblem.php?pid=2859
题意:给出一个由小写字母构成的字符矩阵, 问它的最大对称子矩阵的边长.最大子矩阵要求按从左下到右上的对角线对称.
思路:
当前点右上方能构成对称矩阵←这个点(本列向上)与(本行向右)对称+右上那个点能构成对称矩阵.
考虑dp. dp[i][j]表示(i,j)这个点能构成最大的子矩阵宽度.
递推式: now表示(i,j)这个点[(本列向上)与(本行向右)对称]的最长长度,
我觉得我是O(n^3)的复杂度...怎么过的了..数据水了吧...
代码:
#include<bits/stdc++.h>
#define fuck(x) std::cout<<"["<<#x<<"->"<<x<<"]"<<endl;
using namespace std;
typedef long long ll;
const int M=2e5+5;
const int inf=1e9+5;
const int mod=1e9+7;
//memset(a,0x3f,sizeof(a));
char a[1005][1005];
int dp[1005][1005];
int n;
int cal(int x,int y) {
int ans=0;
for(int i=x,j=y; i>=1&&j<=n; i--,j++) {
if(a[i][y]==a[x][j])
ans++;
else
break;
}
return ans;
}
int main() {
while(~scanf("%d",&n)&&n) {
for(int i=1; i<=n; i++) {
scanf("%s",a[i]+1);
}
memset(dp,0,sizeof(dp));
for(int i=1; i<=n; i++) {
for(int j=n; j>=1; j--) {
int now=cal(i,j);//本行列对称的个数
// fuck(now);
if(now<=dp[i-1][j+1])
dp[i][j]=max(dp[i][j],now);
else
dp[i][j]=max(dp[i][j],dp[i-1][j+1]+1);
}
}
int ans=0;
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
// printf("[%d,%d]:%d ",i,j,dp[i][j]);
ans=max(ans,dp[i][j]);
}
// puts("");
}
printf("%d\n",ans);
}
return 0;
}