Codeforces 570E - Pig and Palindromes (DP)

状态dp[cnt][x1][y1][x2][y2]表示左边从起点开始走cnt步到x1,y1,右边从终点开始走cnt步到x2,y2的方案数。

因为知道cnt和x1,x2的话就能求出y1,y2,所以可以做个空间优化。但是这样还不够,因为cnt状态只和cnt-1状态有关,所以可以用滚动数组。

转移方程就是当mp[x1][y1]==mp[x2][y2]时(mp为迷宫):

dp[cnt][x1][x2]+=dp[cnt-1][x1-1][x2]
dp[cnt][x1][x2]+=dp[cnt-1][x1-1][x2+1]
dp[cnt][x1][x2]+=dp[cnt-1][x1][x2]
dp[cnt][x1][x2]+=dp[cnt-1][x1][x2+1]


注意m+n的奇偶性不同时最后起点终点回合的位置也是不同的,所以统计答案时要分情况。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#include <set>
#include <cmath>
#define LL long long
#define maxn 505
#define bug(a) cout<<a<<endl;
#define bg cout<<'!'<<endl;
const LL mod = 1e9+7;
LL dp[2][maxn][maxn];


char mp[maxn][maxn];
int n,m;

bool valid(int x,int y){
    if(x<=n-1&&x>=0&&y<=m-1&&y>=0) return 1;
    return 0;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        char s[maxn];
        scanf("%s",s);
        for(int j=0;j<m;j++){
            mp[i][j]=s[j];
        }
    }
    if(mp[0][0]!=mp[n-1][m-1]){
        printf("0\n");
        return 0;
    }
    dp[0][0][n-1]=1;
    int tot=(m+n-3)/2;
    int cur=0;
    if((m+n)%2==0) tot++;
    for(int i=1;i<=tot;i++){
        cur^=1;
        memset(dp[cur],0,sizeof(dp[cur]));
        for(int j=0;j<=i;j++){
            int x1=i-j,y1=j;
            if(!valid(x1,y1)) continue;
            for(int k=0;k<=i;k++){
                int x2=n-1-i+k,y2=m-1-k;

                if(!valid(x2,y2)) continue;

                if(mp[x1][y1]==mp[x2][y2]){
                    if(x1){
                        (dp[cur][x1][x2]+=dp[cur^1][x1-1][x2])%=mod;
                        if(x2+1<n) (dp[cur][x1][x2]+=dp[cur^1][x1-1][x2+1])%=mod;
                    }
                    (dp[cur][x1][x2]+=dp[cur^1][x1][x2])%=mod;
                    if(x2+1<n) (dp[cur][x1][x2]+=dp[cur^1][x1][x2+1])%=mod;
                }   
            }
        }
    }
    LL res=0;
    if((m+n)&1){
        for(int i=0;i<n-1;i++){
            (res+=dp[cur][i][i])%=mod;
            (res+=dp[cur][i][i+1])%=mod;
        }
        (res+=dp[cur][n-1][n-1])%=mod;
    }
    else {
        for(int i=0;i<n;i++){
            (res+=dp[cur][i][i])%=mod;
        }
    }
    if(m+n==2) res=1;
    printf("%I64d\n",res);
    return 0;
}

/*
3 4
baba
aaba
baab
*/


你可能感兴趣的:(Codeforces 570E - Pig and Palindromes (DP))