P2051 [AHOI2009]中国象棋[线性DP]

Posted saigyouji-yuyuko

tags:

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

最近智商有点不在线。其实一直不在线。

题目


先是想用$f[i][j][k][0/1/2]$表示摆了i行时有j列空着,k列有了一个炮,且当下摆了0/1/2个的状态,转移方程写的出来但是极其繁琐。于是又设法听取评讲者题解修改状态,最后的012完全可以删去。那么仍可以表示这一行那些列摆过1个,那些列摆过0个的种类。转移时分类即可。

$f[i][j][k]+=f[i-1][j][k]$ 什么都不摆

$f[i][j][k]+=(j+1)*f[i-1][j+1][k-1]$  摆1个炮

$f[i][j][k]+=(k+1)*f[i-1][j][k+1]$  摆1个炮

$f[i][j][k]+=(j+1)*(j+2)/2*f[i-1][j+2][k-2]$  摆两个炮,下同

$f[i][j][k]+=(k+1)*(k+2)/2*f[i-1][j][k+2]$  

$f[i][j][k]+=k*(j+1)*f[i-1][j+1][k]$

注意边界就行。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef pair<int,int> pii;
 5 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
 6 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
 7 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
 8 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
 9 template<typename T>inline T read(T&x){
10     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c==-)f=1;
11     while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();return f?x=-x:x;
12 }
13 const int N=100+7,P=9999973;
14 int n,m,ans,f[N][N][N];
15 
16 inline void inc(int&x,int y){(x+=y)>=P?x-=P:1;}
17 
18 int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout);
19     read(n),read(m);if(m<2){printf("%d
",1+n+(n)*(n-1)/2);return 0;}
20     f[1][m][0]=1,f[1][m-1][1]=m,f[1][m-2][2]=m*(m-1)/2;
21     for(register int i=2;i<=n;++i)
22         for(register int j=0;j<=m;++j)
23             for(register int k=0;k<=m-j;++k){
24                 inc(f[i][j][k],f[i-1][j][k]);
25                 if(k)inc(f[i][j][k],(j+1)*f[i-1][j+1][k-1]%P);
26                 inc(f[i][j][k],(k+1)*f[i-1][j][k+1]%P);
27                 if(k>=2)inc(f[i][j][k],((j+1)*(j+2)>>1)*1ll*f[i-1][j+2][k-2]%P);
28                 inc(f[i][j][k],((k+1)*(k+2)>>1)*1ll*f[i-1][j][k+2]%P);
29                 inc(f[i][j][k],1ll*k*(j+1)*f[i-1][j+1][k]%P);
30             }
31     for(register int i=0;i<=m;++i)for(register int j=0;j<=m-i;++j)inc(ans,f[n][i][j]);
32     printf("%d
",ans);
33     return 0;
34 }

 

以上是关于P2051 [AHOI2009]中国象棋[线性DP]的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P2051 [AHOI2009]中国象棋(dp)

Luogu P2051 [AHOI2009]中国象棋 //DP

luogu P2051 [AHOI2009]中国象棋 dp 状态压缩+容斥

Luogu P2051 [AHOI2009]中国象棋 | dp

Luogu P2051 [AHOI2009]中国象棋

luogu P2051 [AHOI2009]中国象棋