洛谷2501 BZOJ1801中国象棋题解

题目链接

BZ链接

其实dp只要把状态想好后转移就很好写了(flag*1)

f[i][j][k]表示到了第i行,有j列放了一个跑,有k列放了两个跑的方案总数

然后大力讨论,转移即可

# include<iostream>
# include<cstdio>
# include<algorithm>
# include<cmath>
# include<cstring>
const int mn = 105;
const int mod = 9999973;
int n,m,ans;
int f[mn][mn][mn];
int main()
{
    scanf("%d%d",&n,&m);
    f[0][0][0]=1;
    for(int i=0;i<n;i++)
        for(int j=0;j<=m;j++)
            for(int k=0;k+j<=m;k++)
            {
                f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%mod;
                //什么都不放
                if(j>=1)
                    f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+1ll*f[i][j][k]*j%mod)%mod;
                //在有跑的一行放一个跑
                if((m-k-j)>=1)
                    f[i+1][j+1][k]=(f[i+1][j+1][k]+1ll*f[i][j][k]*(m-k-j)%mod)%mod;
                //在空地上放一个跑
                if(j>=2)
                    f[i+1][j-2][k+2]=(f[i+1][j-2][k+2]+1ll*f[i][j][k]*(j-1)*j/2%mod)%mod;
                if((m-k-j)>=2)
                    f[i+1][j+2][k]=(f[i+1][j+2][k]+1ll*f[i][j][k]*(m-k-j-1)*(m-k-j)/2%mod)%mod;
                if((m-k-j)>=1 && j>=1)
                    f[i+1][j][k+1]=(f[i+1][j][k+1]+1ll*f[i][j][k]*(m-k-j)*j%mod)%mod;
            }
    for(int i=0;i<=m;i++)
        for(int j=0;j+i<=m;j++)
        ans=(ans+f[n][i][j])%mod;
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-08-21 14:19  logeadd  阅读(184)  评论(0编辑  收藏  举报