状压DP,用dp[i][j][k]来表示第i行的状态为第j个时,前i行总共放置k个king的方案数,则dp[i][j][k] = sum(dp[i-1][y][k-num[j]]),
其中y是第i-1行的状态,num[j]为第i行的j状态所放置的king的个数,注意结果要用long long 保存。
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <map>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef __int64 int64;
typedef long long ll;
#define M 100005
#define mod 1000000007
int n , k , status[1500] , num[1500] , tot;
ll dp[15][300][200];
void Init()
{
tot = 0;
ll i , sum = 1<<n;
for (i = 0 ; i < sum ; i++)
{
if ((i >> 1) & i)continue;
status[tot] = i;
ll tmp = i;
num[tot] = 0;
while (tmp)num[tot]+=tmp%2,tmp/=2;
tot++;
}
}
ll Solve()
{
int i , j , kk , l , cnt = 0;
memset(dp , 0 , sizeof dp);
dp[0][0][0] = 1;
for (i = 1 ; i <= n ; i++)
{
for (j = 0 ; j < tot ; j++)
{
for (kk = 0 ; kk <= k ; kk++)
{
for (l = 0 ; l < tot ; l++)
{
if (status[j]&status[l] || (status[j]>>1)&status[l] || (status[j]<<1)&status[l] || kk-num[j]<0)continue;
dp[i][j][kk] += dp[i-1][l][kk-num[j]];
}
}
}
}
ll ret = 0;
for (i = 0 ; i < tot ; i++)ret += dp[n][i][k];
return ret;
}
int main()
{
scanf("%d%d",&n,&k);
Init();
printf("%lld\n",Solve());
return 0;
}