[bzoj1801]chess 中国象棋

[bzoj1801]chess 中国象棋


观察到摆放其实实在要求每行每列不能出现三个棋子  

记f[k][i][j]为第k行时当前还有i列还能放两个棋子,j列还能放一个棋子的方案数

状态转移见代码

  • 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; 
int n,m;
ll mod=9999973;
ll f[110][110][110];

int main()
{
	scanf("%d%d",&n,&m);
	f[0][n][0]=1;
	for(int i=1;i<=m;i++){
		for(int j=0;j<=n;j++)
			for(int k=0;k<=n;k++)if(j+k<=n)
				f[i][j][k]=f[i-1][j][k];//不放
		for(int j=0;j<=n;j++)
			for(int k=0;k<=n;k++)if(j+k<=n){
				f[i][j][k]+=f[i-1][j][k+1]*(k+1)%mod;
				if(k)f[i][j][k]+=f[i-1][j+1][k-1]*(j+1)%mod;
				//1个
		}
		for(int j=0;j<=n;j++)
			for(int k=0;k<=n;k++)if(j+k<=n){
				f[i][j][k]+=f[i-1][j][k+2]*(k+2)*(k+1)/2%mod;
				f[i][j][k]+=f[i-1][j+1][k]*(j+1)*k%mod;
				if(k>=2)f[i][j][k]+=f[i-1][j+2][k-2]*(j+2)*(j+1)/2%mod;
				f[i][j][k]%=mod;
				//2个
			}
	}
	ll ans=0;
	for(int i=0;i<=n;i++)
		for(int j=0;j<=n;j++)if(i+j<=n){
			ans=(ans+f[m][i][j])%mod;
		}
	printf("%lld\n",(ans+mod)%mod);
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/82807615