BZOJ1801: [Ahoi2009]chess 中国象棋
Posted QYP_2002
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1801: [Ahoi2009]chess 中国象棋相关的知识,希望对你有一定的参考价值。
1801: [Ahoi2009]chess 中国象棋
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1910 Solved: 1104
[Submit][Status][Discuss]
Description
在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。
请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧.
Input
一行包含两个整数N,M,中间用空格分开.
Output
输出所有的方案数,由于值比较大,输出其mod 9999973
Sample Input
1 3
Sample Output
7
HINT
除了在3个格子中都放满炮的的情况外,其它的都可以.
100%的数据中N,M不超过100
50%的数据中,N,M至少有一个数不超过8
30%的数据中,N,M均不超过6
思路{
在DP过程中发现问题的一些限制,特征,能够找到问题的突破口.
比如此题:发现每行每列都不能放超过2个棋子,那么我们从上述限制设转移方程,
f[i][j][k]为到第i行有j列放1个,k列放2个.
仔细考虑清楚各种情况算组合数转移.
}
#include<bits/stdc++.h> #define RG register #define il inline #define N 200 #define mod 9999973 #define LL long long using namespace std; LL dp[N][N][N];int n,m; LL c(int x){return (x*(x-1))/2;} void update(LL & x){x%=mod;} int main(){ scanf("%d%d",&n,&m); dp[0][0][0]=1; for(int i=0;i<n;++i){ for(int j=0;j<=m;++j) for(int k=0;k+j<=m;++k){ dp[i+1][j][k]+=dp[i][j][k];update(dp[i+1][j][k]); if(m-j-k>0){ dp[i+1][j+1][k]+=dp[i][j][k]*(m-j-k); update(dp[i+1][j+1][k]);//放一个在空位上 } if(j){ dp[i+1][j-1][k+1]+=dp[i][j][k]*j; update(dp[i+1][j-1][k+1]);//放一个在已经放过的上 } if(m-j-k>0){ dp[i+1][j+2][k]+=dp[i][j][k]*c(m-j-k); update(dp[i+1][j+2][k]);//放两个在空位上 } if(m-j-k>0){ dp[i+1][j][k+1]+=dp[i][j][k]*(m-j-k)*j; update(dp[i+1][j][k+1]);//2.1个空1个已放1 } if(j>1){ dp[i+1][j-2][k+2]+=dp[i][j][k]*c(j); update(dp[i+1][j-2][k+2]);//2.都在1 } } }LL Ans(0); for(int i=0;i<=m;++i) for(int j=0;i+j<=m;++j)Ans+=dp[n][i][j],Ans%=mod; cout<<Ans; return 0; }
以上是关于BZOJ1801: [Ahoi2009]chess 中国象棋的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1801 [Ahoi2009]chess 中国象棋
bzoj1801: [Ahoi2009]chess 中国象棋