【佛山市选2013】回文子序列
Description
回文序列是指左右对称的序列。例如1 2 3 2 1是回文序列,但是1 2 3 2 2就不是。我们会给定一个N×M的矩阵,你需要从这个矩阵中找出一个P×P的子矩阵,使得这个子矩阵的每一列和每一行都是回文序列。
Input
第一行有两个正整数N, M。
接下来是n行,代表一个N×M的矩阵,矩阵的每个元素都是值不超过31415926的正整数。
Output
输出符合条件的子矩阵的最大大小P。
Sample Input
5 10
1 2 3 3 2 4 5 6 7 8
1 2 3 3 2 4 5 6 7 8
1 2 3 3 2 4 5 6 7 8
1 2 3 3 2 4 5 6 7 8
1 2 3 9 10 4 5 6 7 8
Sample Output
4
Data Constraint
对于20%数据 1 ≤ N, M ≤ 10
对于所有数据 1 ≤ N, M ≤ 300
反思&题解
比赛&正解思路:
枚举每行每列,找出一行中的回文串,再
判断区间内一列中的回文串,
完美过掉(听说还可以打manacher ,不过我太弱了暂时不会 )
反思: 感动又有一道签到题了(其实数据有点水,不然过不了)
CODE
#include<bits/stdc++.h>//原谅我又把一道水题的代码打得又臭又长
using namespace std;
int n,m,a[305][305],ans,ansl,ansr;
int main()
{
scanf("%d%d",&n,&m);
int i,j,k;
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
scanf("%d",&a[i][j]);
}
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
int l=j,r=j;
while (l>1 && r<m)
{
if (a[i][l-1]==a[i][r+1])
{
l--;
r++;
}
else break;
}
bool flag=true;
if (n-i+1>=r-l+1)
{
for (k=i;k<=i+r-l;k++)
{
int ll=l,rr=r;
while (ll<=rr)
{
if (a[k][ll]==a[k][rr])
{
ll++;
rr--;
}
else break;
}
if (ll<rr)
{
flag=false;
break;
}
}
if (flag)
{
int ll,rr;
for (k=l;k<=r;k++)
{
int ll=i,rr=i+r-l;
while (ll<=rr)
{
if (a[ll][k]==a[rr][k])
{
ll++;
rr--;
}
else break;
}
if (ll<rr)
{
flag=false;
break;
}
}
}
}
else flag=false;
if (flag)
{
if (ans<r-l+1) ans=r-l+1;
}
}
for (j=1;j<=m-1;j++)
{
int l=j,r=j+1;
if (a[i][l]!=a[i][r]) continue;
while (l>1 && r<m)
{
if (a[i][l-1]==a[i][r+1])
{
l--;
r++;
}
else break;
}
bool flag=true;
if (n-i+1>=r-l+1)
{
for (k=i;k<=i+r-l;k++)
{
int ll=l,rr=r;
while (ll<=rr)
{
if (a[k][ll]==a[k][rr])
{
ll++;
rr--;
}
else break;
}
if (ll<rr)
{
flag=false;
break;
}
}
if (flag)
{
for (k=l;k<=r;k++)
{
int ll=i,rr=i+r-l;
while (ll<=rr)
{
if (a[ll][k]==a[rr][k])
{
ll++;
rr--;
}
else break;
}
if (ll<rr)
{
flag=false;
break;
}
}
}
}
else flag=false;
if (flag)
{
if (ans<r-l+1) ans=r-l+1;
}
}
}
printf("%d\n",ans);
return 0;
}