bzoj1801: [Ahoi2009]chess 中国象棋

本文介绍了一道关于中国象棋炮的放置问题的算法题目,通过动态规划的方法求解在N行M列的棋盘上,放置多个炮使得它们不能互相攻击的所有方案数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1801: [Ahoi2009]chess 中国象棋

Time Limit: 10 Sec   Memory Limit: 64 MB
Submit: 2205   Solved: 1298
[ Submit][ Status][ Discuss]

Description

在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧.

Input

一行包含两个整数N,M,中间用空格分开.

Output

输出所有的方案数,由于值比较大,输出其mod 9999973

Sample Input

1 3

Sample Output

7

HINT

除了在3个格子中都放满炮的的情况外,其它的都可以.

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

Source

[ Submit][ Status][ Discuss]



题解:OTZ。。。

点击打开链接

f[i][j][k]表示截止到第i行为止,在所有的列中有一个炮的有j列,有2个炮的有k列。

推想出以下6种状态:

1:在下一行什么也不放: f[i+1][j][k]=f[i+1][j][k]+f[i][j][k];

2:在下一行中找一个0个炮的列去放一个炮:  f[i+1][j+1][k]=f[i+1][j+1][k]+f[i][j][k]*(m-j-k);

3:在下一行中找一个1个炮的列去放一个炮:  f[i+1][j-1][k+1]=f[i+1][j-1][k+1]+f[i][j][k]*j;

4:在下一行中找两个0个炮的列去分别放一个炮:  f[i+1][j+2][k]=f[i+1][j+2][k]+f[i][j][k]*(m-j-k)*(m-j-k-1)/2;

(这里运用了组合数公式,因为有m-j-k个0个炮的列,任选两个进行组合,一共有C2m-j-k种放法,化简开来就是有(m-j-k)*(m-j-k-1)/2种)

5:在下一行中找一个0个炮的列和一个1个炮的列分别去放一个炮:  f[i+1][j][k+1]=f[i+1][j][k+1]+f[i][j][k]*(m-j-k)*j;

6:在下一行中找两个1个炮的列去分别放一个炮:  f[i+1][j-2][k+2]=f[i+1][j-2][k+2]+f[i][j][k]*j*(j-1)/2;

最后的ans是所有的f[n]加起来:  ans=ans+f[n][j][k];


代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,i,j,k;
long long ans,f[101][101][101];
int main(){
	scanf("%d%d",&n,&m);
	f[0][0][0]=1;
	for(i=1;i<=n;i++)
	 for(j=0;j<=m;j++)
	  for(k=0;k<=m-j;k++){
	  	f[i][j][k]=f[i-1][j][k];
	  	if(j)f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1);
	  	if(k&&j<m)f[i][j][k]+=f[i-1][j+1][k-1]*(j+1);
	  	if(j>1)f[i][j][k]+=f[i-1][j-2][k]*((m-j-k+2)*(m-j-k+1)/2);
	  	if(k>1&&j+2<=m)f[i][j][k]+=f[i-1][j+2][k-2]*((j+2)*(j+1)/2);
	  	if(j&&k)f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1);
	  	f[i][j][k]%=9999973;
	  }
	for(i=0;i<=m;i++)
	 for(j=0;j<=m;j++)ans+=f[n][i][j];
	printf("%lld\n",ans%9999973);   
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值