題目描述
在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;
}