Codeforces 570E - Pig and Palindromes (DP)

来源:互联网 发布:软件测试中心 编辑:程序博客网 时间:2024/04/28 14:30

状态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 4babaaababaab*/


0 0