P2051 [AHOI2009]中国象棋 DP

题目描述

这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!

输入输出格式

输入格式:

一行包含两个整数N,M,之间由一个空格隔开。

输出格式:

总共的方案数,由于该值可能很大,只需给出方案数模9999973的结果。

输入输出样例

输入样例#1:  复制
1 3
输出样例#1:  复制
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列有2个棋子的方案数,枚举当前行填棋子的个数及位置可以很快得出转移方程。

代码:

 1 #include"bits/stdc++.h"
 2 #define db double
 3 #define ll long long
 4 #define vec vector<ll>
 5 #define Mt  vector<vec>
 6 #define ci(x) scanf("%d",&x)
 7 #define cd(x) scanf("%lf",&x)
 8 #define cl(x) scanf("%lld",&x)
 9 #define pi(x) printf("%d\n",x)
10 #define pd(x) printf("%f\n",x)
11 #define pl(x) printf("%lld\n",x)
12 #define rep(i, n) for(int i=0;i<n;i++)
13 using namespace std;
14 const int N = 1e6 + 5;
15 const int mod = 1e9 + 7;
16 const int MOD = 9999973;
17 const int inf = 0x3f3f3f3f;
18 const db PI = acos(-1.0);
19 const db eps = 1e-10;
20 ll f[105][105][105];
21 int n,m;
22 ll C(int x)
23 {
24     return 1ll*x*(x-1)/2%MOD;
25 }
26 int main()
27 {
28     ci(n),ci(m);
29     memset(f,0, sizeof(f));
30     f[0][0][0]=1;
31     for(int i=0;i<n;i++){
32         for(int j=0;j<=m;j++){
33             for(int k=0;k+j<=m;k++){
34                 if(f[i][j][k]!=0){
35                     f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%MOD;
36                     if(m-k-j>=1) f[i+1][j+1][k]=(f[i+1][j+1][k]+(m-k-j)*f[i][j][k]%MOD)%MOD;
37                     if(j>=1) f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+j*f[i][j][k]%MOD)%MOD;
38                     if(m-k-j>=2) f[i+1][j+2][k]=(f[i+1][j+2][k]+C(m-k-j)*f[i][j][k]%MOD)%MOD;
39                     if(j>=2) f[i+1][j-2][k+2]=(f[i+1][j-2][k+2]+C(j)*f[i][j][k]%MOD)%MOD;
40                     if(j>=1&&m-k-j>=1) f[i+1][j][k+1]=(f[i+1][j][k+1]+j*(m-k-j)*f[i][j][k]%MOD)%MOD;
41                 }
42             }
43         }
44     }
45     ll ans=0;
46     for(int j=0;j<=m;j++){
47         for(int k=0;k+j<=m;k++){
48             ans=(ans+f[n][j][k])%MOD;
49         }
50     }
51     pl(ans);
52 }

猜你喜欢

转载自www.cnblogs.com/mj-liylho/p/9428103.html
今日推荐