炮(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 }