题目
在一个n∗mn*mn∗m的棋盘中放若干个炮(可以不放),问有多少种方法使其不能相互攻击
分析
也就是每行每列只能放0到2个炮
设dp[i][j][k]dp[i][j][k]dp[i][j][k]表示前iii行有jjj列只放1个炮,有kkk列放两个炮的方案,其实配着代码讲更容易
代码
#include <cstdio>
#define rr register
using namespace std;
const int mod=9999973; int n,m,dp[101][101][101];
inline void mo(int &x,int y){x=(x+y>=mod)?(x+y-mod):(x+y);}
signed main(){
scanf("%d%d",&n,&m);
dp[0][0][0]=1; rr int ans=0;
for (rr int i=0;i<n;++i)
for (rr int j=0;j<=m;++j)
for (rr int k=0;j+k<=m;++k){
mo(dp[i+1][j][k],dp[i][j][k]);
if (m-j-k) mo(dp[i+1][j+1][k],dp[i][j][k]*(m-j-k)%mod);//在空的m-j-k列选择放一个炮
if (j) mo(dp[i+1][j-1][k+1],dp[i][j][k]*j%mod);//在j列中挑一个位置再放1个炮
if (m-j-k>1) mo(dp[i+1][j+2][k],1ll*dp[i][j][k]*((m-j-k)*(m-j-k-1)>>1)%mod);//在空的m-j-k列两个位置放一个炮
if (m-j-k&&j) mo(dp[i+1][j][k+1],1ll*dp[i][j][k]*(m-j-k)*j%mod);//在空的m-j-k列放一个炮,在j列放一个炮
if (j>1) mo(dp[i+1][j-2][k+2],1ll*dp[i][j][k]*(j*(j-1)>>1)%mod);//在j列中挑两个位置放炮
}
for (rr int i=0;i<=m;++i)
for (rr int j=0;i+j<=m;++j) mo(ans,dp[n][i][j]);
return !printf("%d",ans);
}
本文探讨了一个关于在n*m的棋盘中放置炮的算法问题,目标是寻找所有可能的放置方式,使得炮之间不会相互攻击。通过动态规划的方法,定义了状态转移方程,并给出了详细的代码实现。
729

被折叠的 条评论
为什么被折叠?



