题目
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
3 2
Sample Output
16
Hint
转移方程 dp[i][j][r+num[j]] += dp[i-1][k][r];
第一维代表行数, 第二维代表状态, 第三维代表在第i行选择j状态下从第一行到该行已有的国王个数。
dp[i][j][x]的值代表第一行到第i行,第i行选择j状态下目前拥有x个国王个数的方案数。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int status[110], num[110];
long long dp[10][110][30];
int main(){
int n, m, i, cont, x, y, k, r, j;
scanf("%d %d", &n, &m);
cont = 0;
memset(num, 0, sizeof(num));
memset(status, 0, sizeof(status));
memset(dp, 0, sizeof(dp));
for(i = 0; i <= (1<<n)-1; i++){
if(!(i&(i<<1))){
status[cont] = i;
x = i;
while(x){
if(x&1)
num[cont]++;
x >>= 1;
}
cont++;
}
}
for(i = 0; i < cont; i++)
dp[1][i][num[i]] = 1;
for(i = 2; i <= n; i++){
for(j = 0; j < cont; j++){
x = status[j];
for(k = 0; k < cont; k++){
y = status[k];
if(!(x & (y << 1)) && !(x & y) && !(x & (y >> 1))){
for(r = 0; r <= m; r++)
dp[i][j][r+num[j]] += dp[i-1][k][r];
}
}
}
}
long long ans = 0;
for(i = 0; i < cont; i++){
ans += dp[n][i][m];
}
printf("%lld", ans);
return 0;
}