【DP】中国象棋

题目描述

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

输入

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

输出

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

样例输入
1 3
样例输出
7
数据范围限制

30% 的数据中 N 和 M 均不超过 6
50% 的数据中 N 和 M 至少有一个数不超过 8
100% 的数据中 N 和 M 不超过 100


只要每行每列摆的数量不超过2。
设f[i][l1][l2]为截止i行,有l1列摆了1个炮,有l2列摆了2个炮。
然后分6种情况讨论… …(头裂


Code

#include<cstdio>
int n,m;
long long ans;
long long f[101][101][101],C[1001],mod =  9999973;
int main(){
 scanf("%d%d",&n,&m);
 for(int i = 1; i <= m; ++i)  //预处理
   C[i] = ((i*(i-1))>>1)%mod; 
 f[0][0][0] = 1;
 for(int i = 1; i <= n; ++i)
   for(int l1 = 0; l1 <= m; ++l1)
     for(int l2 = 0; l1+l2 <= m; ++l2){
      f[i][l1][l2] = f[i-1][l1][l2];   //不放 
      if(l1>0) f[i][l1][l2] = (f[i][l1][l2] + f[i-1][l1-1][l2] * (m-(l1-1+l2)) % mod) %mod;  
      //0放1 
      if(l2>0) f[i][l1][l2] = (f[i][l1][l2] + f[i-1][l1+1][l2-1]*(l1+1) % mod) %mod;  
      //1放1 
      if(l1>1) f[i][l1][l2] = (f[i][l1][l2] + f[i-1][l1-2][l2] * C[(m-(l1-2+l2))] % mod) %mod; 
      //0放2 
      if(l2>0&&l1>0) f[i][l1][l2] = (f[i][l1][l2] + f[i-1][l1][l2-1] * (m-(l1+l2-1))*(l1) % mod) %mod;  
      //0放1,1放1 
      if(l2>1)  f[i][l1][l2] = (f[i][l1][l2] + f[i-1][l1+2][l2-2]*C[l1+2] % mod) %mod; 
       //1放2 
     }
 for(int l1 = 0; l1 <= m; ++l1)
   for(int l2 = 0; l2+l1 <= m; ++l2)
     ans = (ans+f[n][l1][l2])%mod;
 printf("%lld", ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值