Codeforces 570E - Pig and Palindromes - [滚动优化DP]

题目连接:https://codeforces.com/problemset/problem/570/Ec++

 

题意:优化

给出 $n \times m$ 的网格,每一格上有一个小写字母,如今从 $(1,1)$ 位置走到 $(n,m)$ 位置,要求通过路径构成一个回文串。spa

要求走路方向保证坐标不会减少(即只能往下或者往右走),要求你给出路径方案数目。code

 

题解:blog

考虑 $f[x_1][y_1][x_2][y_2]$ 表示一端从 $(1,1)$ 出发,走到了 $(x_1,y_1)$,同时另外一端从 $(n,m)$ 出发,走到了 $(x_2,y_2)$,此时造成回文串的数目。ci

这个是不难维护的,主要问题是这个维数过多,开不下。而后不难发现,若是用 $f[step][x_1][x_2]$ 来维护,能够经过步数 $step$ 和 $x$ 算出 $y$,get

而后更进一步能够发现 $step$ 不须要所有维护,能够使用滚动优化。it

 

AC代码:class

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int SIZE=505;

int n,m;
char mp[SIZE][SIZE];
ll f[2][SIZE][SIZE];

inline bool In(int x,int y)
{
    return 1<=x && x<=n && 1<=y && y<=m;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);

    int now=0;
    memset(f[now],0,sizeof(f[now]));
    f[now][1][n]=(ll)(mp[1][1]==mp[n][m]);
    for(int step=1;step<=(n+m)/2-1;step++)
    {
        now^=1;
        memset(f[now],0,sizeof(f[now]));
        for(int x1=1;x1<=n;x1++)
        {
            for(int x2=n;x2>=1;x2--)
            {
                int y1=step+2-x1, y2=n+m-step-x2;
                if(!In(x1,y1) || !In(x2,y2)) continue;
                if(mp[x1][y1]!=mp[x2][y2]) continue;

                f[now][x1][x2]+=f[now^1][x1][x2];
                f[now][x1][x2]%=mod;

                f[now][x1][x2]+=f[now^1][x1-1][x2+1];
                f[now][x1][x2]%=mod;

                f[now][x1][x2]+=f[now^1][x1-1][x2];
                f[now][x1][x2]%=mod;

                f[now][x1][x2]+=f[now^1][x1][x2+1];
                f[now][x1][x2]%=mod;
            }
        }
    }

    ll ans=0;
    if((n+m)%2)
    {
        for(int i=1;i<=n;i++) ans+=f[now][i][i], ans%=mod;
        for(int i=1;i<n;i++) ans+=f[now][i][i+1], ans%=mod;
    }
    else
    {
        for(int i=1;i<=n;i++) ans+=f[now][i][i], ans%=mod;
    }
    cout<<ans<<endl;
}
相关文章
相关标签/搜索