BZOJ 4806 : 炮
Posted wy_2016
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4806 : 炮相关的知识,希望对你有一定的参考价值。
题意:炮在同一行或是同一列超过三个就可以出现一个吃掉另一个的情况,求在n*m的棋盘上放置炮且两两不可吃的情况总数。
用dp的方法来完成计数,可以考虑这样一个状态,枚举到第x行,共有 a个“含2个炮的列”, b个“含1个炮的列”, c个“含0个炮的列”,注意到a+b+c等于定值,显然这是可以优化的。基本思路大概这样。
dp[i][j][k]表示前i行里,具有{有j个“含1个炮的列”, k个“含2个炮的列”}性质的情况总数
最后求ans时,要对dp[n][][]求总和
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int mod=999983; const int N=105; int n,m; LL dp[N][N][N]; int cal(int x) { return x*(x-1)/2%mod; } int main() { while(~scanf("%d%d",&n,&m)) { dp[0][0][0]=1; for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) for(int k=0;k+j<=m;k++) { dp[i][j][k]=dp[i-1][j][k]; if(j>=1) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j-1][k]*(m-k-j+1))%mod; if(j>=2) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j-2][k]*cal(m-k-j+2))%mod; if(k>=1) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j+1][k-1]*(j+1))%mod; if(k>=1) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k-1]*(m-k-j+1)%mod*j)%mod; if(k>=2) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j+2][k-2]*cal(j+2))%mod; } int ans=0; for(int i=0;i<=m;i++) for(int j=0;i+j<=m;j++) ans=(ans+dp[n][i][j])%mod; printf("%d\n",ans); } }
以上是关于BZOJ 4806 : 炮的主要内容,如果未能解决你的问题,请参考以下文章