标签:can 有一个 tom max 个数 输出 中国象棋 map margin
这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!
输入格式:
一行包含两个整数N,M,之间由一个空格隔开。
输出格式:
总共的方案数,由于该值可能很大,只需给出方案数模9999973的结果。
1 3
7
样例说明
除了3个格子里都塞满了炮以外,其它方案都是可行的,所以一共有2*2*2-1=7种方案。
数据范围
100%的数据中N和M均不超过100
50%的数据中N和M至少有一个数不超过8
30%的数据中N和M均不超过6
每行每列最多放两个炮.
设f[i][j][k]代表前i行,有j列有一个炮,有k列有两个炮的方案数.
那么分6种情况转移.
1.不放
2.放一个炮,放在没有炮的列地方
3.放一个炮,放在有一个炮的列
4.放两个炮,都放在空列
5.放两个炮,都放在有一个炮的列
6.放两个炮,一个放在空列,一个放在有一个炮的列.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<algorithm> 7 #include<map> 8 #include<complex> 9 #include<queue> 10 #include<stack> 11 #include<cmath> 12 #include<set> 13 #include<vector> 14 #define maxn 110 15 #define mod 9999973 16 #define LL long long 17 using namespace std; 18 LL f[maxn][maxn][maxn]; 19 LL C(int x){ 20 return (LL)x*(x-1)/2; 21 } 22 int main(){ 23 int n,m; 24 scanf("%d%d",&n,&m); 25 f[0][0][0]=1; 26 for(int i=1;i<=n;i++) 27 for(int j=0;j<=m;j++) 28 for(int k=0;k<=m;k++){ 29 if(j+k>m) break; 30 LL &ans=f[i][j][k]; 31 ans=(ans+f[i-1][j][k])%mod;//一个都不放 32 if(j-1>=0)ans=(ans+f[i-1][j-1][k]*(m-j-k+1)%mod)%mod;//放一个,放在没有的列上. 33 if(k-1>=0)ans=(ans+f[i-1][j+1][k-1]*(j+1)%mod)%mod;//放一个,放在有一个的列上. 34 if(j-2>=0)ans=(ans+(f[i-1][j-2][k]*C(m-j-k+2))%mod)%mod;//放两个,都放在空位. 35 if(k-2>=0)ans=(ans+f[i-1][j+2][k-2]*C(j+2)%mod)%mod;//放两个,都放在有一个的列上. 36 if(k-1>=0)ans=(ans+(f[i-1][j][k-1]*(m-j-k+1)%mod)*j%mod)%mod; 37 } 38 LL Ans=0; 39 for(int j=0;j<=m;j++) 40 for(int k=0;k<=m;k++) 41 Ans+=f[n][j][k],Ans%=mod; 42 printf("%lld",Ans%mod); 43 return 0; 44 } 45
标签:can 有一个 tom max 个数 输出 中国象棋 map margin
原文地址:http://www.cnblogs.com/pantakill/p/7502692.html