首页 > 代码库 > BZOJ 4806 : 炮
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 : 炮
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。