HDU 4618 Palindrome Sub-Array 暴力

Palindrome Sub-Array

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=4618

Description

 A palindrome sequence is a sequence which is as same as its reversed order. For example, 1 2 3 2 1 is a palindrome sequence, but 1 2 3 2 2 is not. Given a 2-D array of N rows and M columns, your task is to find a maximum sub-array of P rows and P columns, of which each row and each column is a palindrome sequence.

  

Input

  The first line of input contains only one integer, T, the number of test cases. Following T blocks, each block describe one test case.
  There is two integers N, M (1<=N, M<=300) separated by one white space in the first line of each block, representing the size of the 2-D array.
  Then N lines follow, each line contains M integers separated by white spaces, representing the elements of the 2-D array. All the elements in the 2-D array will be larger than 0 and no more than 31415926.
  

Output

  For each test case, output P only, the size of the maximum sub-array that you need to find.
  

Sample Input

1
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

Hint

题意

给你一个n,m的矩形,你需要找到一个最大正方形,使得每一行每一列都是回文的

输出正方形的边长

题解:

首先把奇数位置都填上-1,然后这样所有回文的东西都是奇数长度了

暴力预处理出以每一个数为中心,能够向上,向左边扩展多少

然后我们在n^2暴力枚举回文正方形的中心点,再O(N)的去check最大能扩展多少就好了

代码

#include<bits/stdc++.h>
using namespace std;

const int maxn = 701;
int M[maxn][maxn];
int M2[maxn][maxn];
int Len1[maxn][maxn],Len2[maxn][maxn];
int n,m;
void init()
{
    memset(M,0,sizeof(M));
    memset(M2,0,sizeof(M2));
    memset(Len1,0,sizeof(Len1));
    memset(Len2,0,sizeof(Len2));
}
void solve()
{
    init();
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&M2[i][j]);

    for(int i=1;i<=2*n+1;i++)
    {
        for(int j=1;j<=2*m+1;j++)
        {
            if(i%2==1||j%2==1)M[i][j]=-1;
            else M[i][j]=M2[i/2][j/2];
        }
    }

    n=n*2+1;
    m=m*2+1;

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int l = 0;
            for(int k=0;j-k>=1&&j+k<=m;k++)
            {
                if(M[i][j-k]==M[i][j+k])
                    l=k;
                else
                    break;
            }
            Len1[i][j]=l;
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int l = 0;
            for(int k=0;i+k<=n&&i-k>=1;k++)
            {
                if(M[i+k][j]==M[i-k][j])
                    l=k;
                else
                    break;
            }
            Len2[i][j]=l;
        }
    }

    int ans = 0;

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int Min1 = 1<<30;
            int Min2 = 1<<30;
            for(int l=0;i-l>=1&&i+l<=n&&j+l<=m&&j-l>=1;l++)
            {
                Min1=min(Min1,Len2[i][j-l]),Min1=min(Min1,Len2[i][j+l]);
                Min2=min(Min2,Len1[i+l][j]),Min2=min(Min2,Len1[i-l][j]);
                if(Min1<l||Min2<l)break;
                if(M[i][j]==-1)ans = max(ans,l);
                else ans = max(ans,l);
            }
        }
    }

    cout<<ans<<endl;
    return;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值