标签:href 思想 根据 pre new ble nbsp https class
题目大意:给定一个$n*m$的棋盘,求放三个“炮”使它们不共行也不共列的方案数。($n,m$$<=100$)
这题主要是转移比较困难,因为情况比较多,所以需要冷静大胆细心地进行分情况讨论。
首先我们还是设计出状态:设$f[i][j][k]$表示前$i$行,放1枚棋子的有$j$列,放2枚棋子的有$k$列的方案数。
我们这样思考:放几个?放在哪?
(f[i][j][k]+=f[i-1][j][k])%=moder;
if(k-1>=0) (f[i][j][k]+=f[i-1][j+1][k-1]*(j+1))%=moder;
if(j-1>=0) (f[i][j][k]+=f[i-1][j-1][k]*(m-k-j+1))%=moder;
if(j-2>=0) (f[i][j][k]+=f[i-1][j-2][k]*C(m-k-j+2))%=moder;
if(k-2>=0) (f[i][j][k]+=f[i-1][j+2][k-2]*C(j+2))%=moder;
if(k-1>=0) (f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1))%=moder;
列出了转移方程,我们的代码也就写完了(雾)。
Code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 typedef long long ll; 6 const ll moder=9999973; 7 8 int n,m; 9 ll ans,f[105][105][105]; 10 11 ll C(int x) 12 { 13 return (x*(x-1))>>1; 14 } 15 16 int main() 17 { 18 scanf("%d%d",&n,&m); 19 f[0][0][0]=1; 20 for(int i=1;i<=n;i++) 21 for(int j=0;j<=m;j++) 22 for(int k=0;k<=m-j;k++) 23 { 24 (f[i][j][k]+=f[i-1][j][k])%=moder; 25 if(k-1>=0) (f[i][j][k]+=f[i-1][j+1][k-1]*(j+1))%=moder; 26 if(j-1>=0) (f[i][j][k]+=f[i-1][j-1][k]*(m-k-j+1))%=moder; 27 if(k-1>=0) (f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1))%=moder; 28 if(k-2>=0) (f[i][j][k]+=f[i-1][j+2][k-2]*C(j+2))%=moder; 29 if(j-2>=0) (f[i][j][k]+=f[i-1][j-2][k]*C(m-k-j+2))%=moder; 30 } 31 for(int j=0;j<=m;j++) 32 for(int k=0;k<=m-j;k++) 33 (ans+=f[n][j][k])%=moder; 34 printf("%lld",ans); 35 return 0; 36 }
转移的时候我竟然想,为什么没有“两个棋子放在同一个之前没放到的列”这种情况。后来才意识到,我们每次面对的,是一行,其实是一个向量,(一维数组)。每一列只能放一颗棋子...
Luogu P2051[AHOI2009]中国象棋【dp】By cellur925
标签:href 思想 根据 pre new ble nbsp https class
原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9745747.html