JZOJ 1667 ( bzoj 1801 ) [ AHOI 2009 ] 中国象棋 —— DP

Posted zinn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JZOJ 1667 ( bzoj 1801 ) [ AHOI 2009 ] 中国象棋 —— DP相关的知识,希望对你有一定的参考价值。

题目:https://jzoj.net/senior/#main/show/1667

首先,一行、一列最多只有 2 个炮;

所以记录一下之前有多少行有 0/1/2 个炮,转移即可;

注意取模!小心在某处爆 int 。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=105,mod=9999973;
int n,m,f[maxn][maxn][maxn],ans;
ll C(int x){return ((ll)x*(x-1)/2)%mod;}
int main()
{
    scanf("%d%d",&n,&m);
    f[m][0][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=m;j++)
            for(int l=m-j;l>=0;l--)
            {
                int k=m-j-l,tmp=f[j][k][l];
                if(!tmp)continue;
                //1
                if(j)(f[j-1][k+1][l]+=(ll)tmp*j)%=mod;//0 -> 1
                if(k)(f[j][k-1][l+1]+=(ll)tmp*k)%=mod;//1 -> 2
                //2
                if(j>1)(f[j-2][k+2][l]+=(ll)tmp*C(j)%mod)%=mod;//0,0 -> 1,1 //%mod
                if(j&&k)(f[j-1][k][l+1]+=(ll)tmp*j%mod*k%mod)%=mod;//0,1 -> 1,2 //%mod
                if(k>1)(f[j][k-2][l+2]+=(ll)tmp*C(k)%mod)%=mod;//1,1 -> 2,2 //%mod
            }
    for(int j=0;j<=m;j++)
        for(int k=0;j+k<=m;k++)
            (ans+=f[j][k][m-j-k])%=mod;
    printf("%d
",ans);
    return 0;
}

 

以上是关于JZOJ 1667 ( bzoj 1801 ) [ AHOI 2009 ] 中国象棋 —— DP的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1692 cogs2005 jzoj1940: [Usaco2007 Dec]队列变换

bzoj 2785 jzoj 2755 2012东莞市选树的计数(计数+dp):

bzoj1801

BZOJ 1801 中国象棋

BZOJ 1801--中国象棋(DP)

bzoj1801 [Ahoi2009]chess 中国象棋