HDOJ 2859 Phalanx (基础DP)

题意:

给出一个 n*n 矩阵,求出最大长度的矩阵使矩阵内部关于反对角线对称。

比如:

3
abx
cyb
zca

答案就是 3,以斜对角线对称。


思路:

一看就是一个DP,那么考虑状态,如何标记一举行,(i,j,len),表示起点在 i ,j,长度为len 的矩形,对于一个矩形来说,可以由两个长度小 1 的子矩形合成来,

令dp[i][j][len]为起点在 i ,j,长度为len 的矩形满足要求的最大边长, 注意这个值要么为 len,要么为0;

那么稍微画一画图就可以得到:

如果满足:dp[i][j+1][len-1]==len-1&&dp[i+1][j][len-1]==len-1且mp[l][r]==mp[i][j]

也就是说两个子矩形是对称矩形,且两个端点也是对称的。

那么(i,j,len)这个矩形也是对称的。

那么就有一个n^3的解法:先枚举矩形长度,再枚举起点,这里要注意一定要先枚举长度,因为从DP方程来看是由小矩形推到大矩形的。

n 是1000,那么就是 1e9 的复杂度,但是这个题给了 5000MS,那么不要怂,莽一波。

但是这里还有哟一个问题:

dp[i][j][len],i,j,len,都是1000,那么就爆内存了,我们继续看DP方程,只用到了两个子答案就是dp[i][j+1][len-1]和dp[i+1][j][len-1],也就是说对于当前len来说,只会用到len-1,而前面的len-2等等都不会用到,那么就用滚动数组优化一下就变成了: dp[1000][1000][2],那么内存问题就解决了。

最后附上毒代码:

#include<stdio.h>
#include<algorithm>
#include<string>
#include<string.h>
#include<queue>
#include<vector>
#include<stack>
#include<math.h>
#include<map>
#include<iostream>
using namespace std;
#define maxn 1050
#define ll long long
char mp[maxn][maxn];
int n,dp[maxn][maxn][2];
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        if(n==0)
            break;
        for(int i=1;i<=n;i++)
            scanf("%s",mp[i]+1);

        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            dp[i][j][0]=1;
        int ans=1;
        int now=1,tmp=0;
        for(int len=2;len<=n;len++)
        {
            for(int i=1;i<=n;i++)
            {
                if(i+len-1>n)
                    break;
                for(int j=1;j<=n;j++)
                {
                    if(j+len-1>n)
                        break;
                    int l=i+len-1;
                    int r=j+len-1;
                    if(mp[l][r]==mp[i][j])
                    {
                        if(dp[i][j+1][tmp]==len-1&&dp[i+1][j][tmp]==len-1)
                            dp[i][j][now]=len;
                        else
                            dp[i][j][now]=0;
                    }
                    else
                        dp[i][j][now]=0;
                    ans=max(ans,dp[i][j][now]);
                }
            }
            if(now==1)
                now=0,tmp=1;
            else
                now=1,tmp=0;
        }
        printf("%d\n",ans);
    }
return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值