国王

https://loj.ac/problem/10170

题目描述

  在(n imes n)的棋盘上放(k)个国王,国王可攻击相邻的(8)个格子,求使它们无法互相攻击的方案总数。

思路

  这道题的(n)比较小,我们考虑直接把棋盘的一行压成一个数,那么如果这个位置放了棋子,这个数的二进制下的数为(1),否则为(0),我们可以先预处理处所有满足条件的行的数,在(dp)列,用(f[i][S][k])表示第(i)行状态为(S),到目前位置共放(k)个棋子的方案数,那么(S)可以从不互相攻击的状态转移过来,直接(dp)即可。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int s[600],p[600];
ll f[11][500][110];
int main()
{
	int n,k,cnt=0;
	scanf("%d%d",&n,&k);
	for(int i=0;i<(1<<n);i++)
	{
		if(i&(i<<1))continue ;
		int sum=0;
		for(int j=0;j<n;j++)
			if(i&(1<<j))sum++;
		p[++cnt]=i;
		s[cnt]=sum;
	}
	f[0][1][0]=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=cnt;j++)
			for(int l=s[j];l<=k;l++)
			{
				for(int r=1;r<=cnt;r++)
					if(!(p[j]&p[r])&&!(p[j]&(p[r]<<1))&&!(p[j]&(p[r]>>1)))
						f[i][j][l]+=f[i-1][r][l-s[j]];
			}
	long long ans=0;
	for(int i=1;i<=cnt;i++)
		ans+=f[n][i][k];
	printf("%lld
",ans);
}
原文地址:https://www.cnblogs.com/fangbozhen/p/11844454.html