题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
输入输出格式
输入格式:
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式:
所得的方案数
输入输出样例
输入样例#1:
3 2
输出样例#1:
16
思路:
状态压缩dp。dp[i][j][t]表示第i行状态为j并且king的数量为t时的结果。
用二进制来表示状态,二进制比特位为1则在该位置放置一个king。
最后统计每一行状态不为0时king的数量为k的总和即可。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stdio.h>
using namespace std;
typedef long long ll;
const int MAXN = 10;
ll dp[MAXN][1 << MAXN][MAXN*MAXN];
int count(int a)
{
int result = 0;
while (a)
{
result++;
a &= (a-1);
}
return result;
}
int main()
{
int n, k;
cin >> n >> k;
memset(dp, 0, sizeof(dp));
dp[0][0][0] = 1;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < (1 << n); j++)
{
if ((j & (j << 1)) > 0)
{
continue;
}
for (int t = 0; t < (1 << n); t++)
{
if ((j & t) > 0)
{
continue;
}
if ((j & (t << 1)) > 0)
{
continue;
}
if (((j << 1) & t) > 0)
{
continue;
}
if ((t & (t << 1)) > 0)
{
continue;
}
int temp = count(t);
for (int x = 0; x <= (k - temp); x++)
{
dp[i][t][x+temp] += dp[i-1][j][x];
}
}
}
}
ll result = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < (1 << n); j++)
{
result += dp[i][j][k];
}
}
cout << result << endl;
return 0;
}