【BZOJ】1801 [Ahoi2009]chess 中國象棋(dp)
阿新 • • 發佈:2018-08-05
發現 lin max def %d print class () line
題目
傳送門:QWQ
分析
發現我們關心的不是棋子的位置,我們只關心棋子數量就ok。
首先每行每列最多兩個棋子。這是顯然的。
然後我覺得本題最難的部分就是對行進行討論,蒟蒻我一直被限制在了對格點討論。。。。
$dp[i][j][k] $放了前$i$行,有$j$列有1個棋子,有$k$列有2個棋子。轉移就很顯然了。
代碼
1 #include <bits/stdc++.h> 2 typedef long long ll; 3 const int maxn=105;const ll MOD=9999973; 4 5 ll dp[maxn][maxn][maxn];6 //dp[i][j][k] 放了前i行,有j列有1個棋子,有k列有2個棋子 7 ll num(int x){return ll(x)*ll(x-1)/2;} 8 using namespace std; 9 int main(){ 10 int n,m;scanf("%d%d",&n,&m); 11 dp[0][0][0]=1; 12 for(int i=0;i<n;i++){ //放第i+1行 13 for(int j=0;j<=m;j++){ 14 for(int k=0;k+j<=m;k++){15 dp[i+1][j][k]=(dp[i+1][j][k]+dp[i][j][k])%MOD; 16 if(m-j-k>=1) dp[i+1][j+1][k]=(dp[i+1][j+1][k]+dp[i][j][k]*(m-j-k))%MOD; 17 if(j>=1) dp[i+1][j-1][k+1]=(dp[i+1][j-1][k+1]+dp[i][j][k]*j)%MOD; 18 if(m-j-k>=2) dp[i+1][j+2][k]=(dp[i+1][j+2][k]+dp[i][j][k]*num(m-j-k))%MOD; 19 if(j>=2) dp[i+1][j-2][k+2]=(dp[i+1][j-2][k+2]+dp[i][j][k]*num(j))%MOD; 20 if(m-j-k>=1 && j>=1) dp[i+1][j][k+1]=(dp[i+1][j][k+1]+dp[i][j][k]*(m-j-k)*j)%MOD; 21 } 22 } 23 } 24 ll ans=0; 25 for(int i=0;i<=m;i++) 26 for(int j=0;j+i<=m;j++) 27 ans=(ans+dp[n][i][j])%MOD; 28 printf("%lld\n",ans); 29 return 0; 30 }
【BZOJ】1801 [Ahoi2009]chess 中國象棋(dp)