纪中暑假集训 2020.08.07【NOIP提高组】模拟 T1:【佛山市选2013】回文子序列

【佛山市选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

反思&题解

比赛&正解思路: O ( n 2 ) O(n^2) 枚举每行每列,找出一行中的回文串,再 O ( n 2 ) O(n^2) 判断区间内一列中的回文串, O ( n 4 ) O(n^4) 完美过掉(听说还可以打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;
}

猜你喜欢

转载自blog.csdn.net/CMC_YXY/article/details/107879957