King

在n*n(n≤10)的棋盘上放k 个国王(可攻击相邻的8 个格子),求使它们无法

互相攻击的方案数。

对于每一行有n个格子时最多可有f(n)种放置方法即f(n)种状态,且f(n)=f(n-1)+f(n-2);(1)=2,f(2)=3;

#include<stdio.h>
#include<string.h>
int f[11]={0,2,3,5,8,13,21,34,55,89,144};
int state[144],staNum[144];
long long dp[10][144][101];
int main()
{
	memset(staNum,0,sizeof(staNum));
	for(int cur=1,j=1;j<(1<<10);j++)
		if(!((j<<1)&j)&&!((j>>1)&j))
		{
			state[cur++]=j;
			for(int k=1;k<(1<<10);k=k<<1)
				if(k&j)	staNum[cur-1]++;
		}
	int N,K;
	while(~scanf("%d %d",&N,&K))
	{
		memset(dp,0,sizeof(dp));
		for(int i=0;i<f[N];i++)
			if(K-staNum[i]>=0)
				dp[0][i][K-staNum[i]]=1;
		for(int i=0;i<N-1;i++)
			for(int j=0;j<f[N];j++)
				for(int k=0;k<=K;k++)
					if(dp[i][j][k])
						for(int jn=0;jn<f[N];jn++)
						{
							int sure=state[jn]&((state[j]<<1)|(state[j]>>1)|(state[j]));
							if(!sure&&(k-staNum[jn]>=0))
								dp[i+1][jn][k-staNum[jn]]+=dp[i][j][k];
						}
		long long sum=0;
		for(int j=0;j<144;j++)
			sum+=dp[N-1][j][0];
		printf("%lld\n",sum);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值