在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;
}