中国象棋 (09 安徽)

2016-06-01 18:24:32

题目链接: 中国象棋 (Codevs No.2227)

                中国象棋 (洛谷 No.2051)

题目大意:

  在一个N*M的棋盘上放置中国象棋中的炮,求使的放置的炮不能互相攻击的方案总数MOD奇怪的数

解法:

  一看就是动态规划(QAQ一看就不会)

  看了看题解理解了一下

  DP[i][j][k]表示现在处于i行,其中已有j列是放置了一个炮,有k列是放置了两个炮(那么空的就是M-j-k喽)

  这个状态一共可能有6种来源

    1.没做改变 直接从上一行推来 DP[i][j][k]+=DP[i-1][j][k]

    2.在空列放置了一个 DP[i][j][k]+=DP[i-1][j-1][k]*(M-k-j+1);                    (后面乘的就是空列的个数)

    3.在空列放置了两个并且不重叠 DP[i][j][k]+=DP[i-1][j-2][k]*(M-k-j+2)*(M-k-j+1)/2;     (后面乘的是在M-k-j+2个空列中取两个的组合数)

    4.在放置了一个的列上再放一个 DP[i][j][k]+=DP[i-1][j+1][k-1]*(j+1);                                                    (后面乘的是放了一个的列个数)

    5.在放置了一个的不同两列上再各放一个 DP[i][j][k]+=DP[i-1][j+2][k-2]*(j+2)*(j+1)/2;              (后面是在j+2个放了一个的列中取两个的组合数)

    6.在放置了一个的列和一个空列上各放一个 DP[i][j][k]+=DP[i-1][j][k-1]*(M-k-j+1)*j;                     (这个好好想想吧,j牵扯到两次改变,领会就好)

 1 //中国象棋 (09 安徽)
 2 //动态规划
 3 #include<stdio.h>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MOD=9999973;
 7 const int maxn=110;
 8 long long DP[maxn][maxn][maxn];
 9 int N,M;
10 long long ans;
11 int main()
12 {
13     scanf("%d %d",&N,&M);
14     DP[0][0][0]=1;
15     for(int i=1;i<=N;i++)
16     {
17         for(int j=0;j<=M;j++)
18         {
19             for(int k=0;k<=M-j;k++)
20             {
21                 DP[i][j][k]+=DP[i-1][j][k];
22                 DP[i][j][k]%=MOD;
23                 if(j>=1)
24                 {
25                     DP[i][j][k]+=DP[i-1][j-1][k]*(M-k-j+1);
26                     DP[i][j][k]%=MOD;
27                 }
28                 if(j>=2)
29                 {
30                     DP[i][j][k]+=DP[i-1][j-2][k]*(M-k-j+2)*(M-k-j+1)/2;
31                     DP[i][j][k]%=MOD;
32                 }
33                 if(j>=1&&k>=1)
34                 {
35                     DP[i][j][k]+=DP[i-1][j][k-1]*(M-k-j+1)*j;
36                     DP[i][j][k]%=MOD;
37                 }
38                 if(k>=1)
39                 {
40                     DP[i][j][k]+=DP[i-1][j+1][k-1]*(j+1);
41                     DP[i][j][k]%=MOD;
42                 }
43                 if(k>=2)
44                 {
45                     DP[i][j][k]+=DP[i-1][j+2][k-2]*(j+2)*(j+1)/2;
46                     DP[i][j][k]%=MOD;
47                 }
48             }
49         }
50     }
51     for(int i=0;i<=M;i++)
52     {
53         for(int j=0;j<=M-i;j++)
54         {
55             ans+=DP[N][i][j];
56             ans%=MOD;
57         }
58     }
59     printf("%lld",ans);
60 }

 

posted @ 2016-06-01 18:44  %Neptune%  阅读(138)  评论(0编辑  收藏  举报