题目大意:一个国王可以攻击到旁边8个位置的格子,现在给出一个N*N的方格,向其中放k个国王,问有多少中摆放方法。
思路:状压DP,f[i][j][k],其中i是行数,j是状态,k是已经取了多少国王。然后暴力枚举状态,看相邻两行之间有没有冲突,若没有冲突,那么就转移。
注意要开long long
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int cnt,k;
long long f[15][1000][100];
inline int Set(int status)
{
int re = 0;
while(status)
re += status&1,status >>= 1;
return re;
}
inline bool Judge(int x,int y)
{
static bool v[11];
memset(v,false,sizeof(v));
int p = 1;
while(x) {
if(x&1) {
if(v[p - 1]|v[p]|v[p + 1]) return false;
v[p] = true;
}
x >>= 1;
++p;
}
p = 1;
while(y) {
if(y&1) {
if(v[p - 1]|v[p]|v[p + 1]) return false;
v[p] = true;
}
y >>= 1;
++p;
}
return true;
}
int main()
{
cin >> cnt >> k;
for(int status = 0; status < (1 << cnt); ++status)
if(Judge(status,0))
f[1][status][Set(status)] = 1;
for(int i = 2; i <= cnt; ++i)
for(int s = 0; s < (1 << cnt); ++s)
for(int _s = 0; _s < (1 << cnt); ++_s)
if(Judge(s,_s)) {
int temp = Set(_s);
for(int z = 0; z <= k - temp; ++z)
f[i][_s][z + temp] += f[i - 1][s][z];
}
long long ans = 0;
for(int status = 0; status < (1 << cnt); ++status)
ans += f[cnt][status][k];
cout << ans << endl;
return 0;
}