济南学习 Day 5 T1 am

炮(cannon)
【题目描述】
众所周知,双炮叠叠将是中国象棋中很厉害的一招必杀技。炮吃子时必须
隔一个棋子跳吃,即俗称“炮打隔子”。 炮跟炮显然不能在一起打起来,于是rly
一天借来了许多许多的炮在棋盘上摆了起来……他想知道,在N×M的矩形方格
中摆若干炮(可以不摆)使其互不吃到的情况下方案数有几种。
棋子都是相同的。
【输入说明】
一行,两个正整数N和M。
【输出说明】
一行,输出方案数mod 999983。
【样例输入】
1 3
【样例输出】
7
【数据范围】
对于40%的数据,N<=4,M<=4
对于70%的数据,N<=100,M<=8
对于100%的数据,N<=100,M<=100

 1 /*
 2   动态规划,状态的表示很巧妙
 3   f[i][j][k]表示放了前i行,有j列放了1个,有k列放了2个,那么就有m-i-j列没放的方案数。然后完成转移。
 4 */
 5 #include<cstdio>
 6 #include<iostream>
 7 #define mod 999983LL
 8 #define N 110
 9 using namespace std;
10 long long f[N][N][N],n,m;
11 int main()
12 {
13     cin>>n>>m;
14     f[0][0][0]=1;
15     for(long long i=1;i<=n;i++)
16       for(long long j=0;j<=m;j++)
17         for(long long k=0;j+k<=m;k++)
18         {
19             f[i][j][k]=f[i-1][j][k];f[i][j][k]%=mod;//不放
20             if(j>=1)f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1);f[i][j][k]%=mod;//空处放1个
21             if(k>=1)f[i][j][k]+=f[i-1][j+1][k-1]*(j+1);f[i][j][k]%=mod;//1个处放1个
22             if(j>=2)f[i][j][k]+=f[i-1][j-2][k]*(m-j-k+2)*(m-j-k+1)/2;f[i][j][k]%=mod;//空处放2个
23             if(k>=2)f[i][j][k]+=f[i-1][j+2][k-2]*(j+2)*(j+1)/2;f[i][j][k]%=mod;//1处放2个
24             if(k>=1)f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1);f[i][j][k]%=mod;//空处和1个处
25         }
26     long long ans=0;
27     for(long long j=0;j<=m;j++)
28       for(long long k=0;j+k<=m;k++)
29         ans+=f[n][j][k],ans%=mod;
30     printf("%d",ans);
31     return 0;
32 }
原文地址:https://www.cnblogs.com/suishiguang/p/6042838.html