topic description
Put k kings on an n×n chessboard, the kings can attack 8 adjacent grids, and find the total number of schemes that prevent them from attacking each other.
input format
A total of one line, containing two integers n and k.
output format
A total of one line, indicating the total number of solutions, if it cannot be placed, output 0.
data range
1 ≤ n ≤ 10,
0 ≤ k ≤ n ^ 2
Input sample:
3 2
Sample output:
16
topic ideas
This question is very similar to the idea of multiple backpacks. Using dfs will time out.
This can be optimized with dp's binary.
Consider a binary 1 representing a king.
1. There cannot be adjacent 1s in the i-th line, such as 6 and its base is 110, which does not meet the meaning of the question.
2. Comparing line i with line i-1, because the meaning of the question says that the surrounding 8 bits 1 0 and 0 1 or 01 and 1 0 do not conform to the meaning of the question.
Considering that this problem is basically solved here.
Problem-solving code:
#include<bits/stdc++.h>
using namespace std;
int cnt = 0;
int s[1 << 12];
int num[1 << 12];
long long f[12][144][1 << 12];//前 i行 有 多少个国王 当在i + 1行时的国王个数是否和前面的第i行相容
int main() {
int n, k;
cin >> n >> k;//n行 k个国王
//预处理 防止相邻的国王在一起 用二进制表示的话 如 i = 6 110 不符合要求
for (int i = 0; i < (1 << n); i++) {
if (!(i & i >> 1)) {
s[cnt++] = i;
for (int j = 0; j < n; j++) {
num[i] += (i >> j & 1);//计算国王的个数
}
}
}
f[0][0][0] = 1;
for (int i = 1; i <= n + 1; i++) { //行数
for (int j = 0; j <= k; j++) { //放的国王数目
for (int a = 0; a < cnt; a++) { // 第i行
for (int b = 0; b < cnt; b++) { //i - 1行
int c = num[s[a]];
if ((j >= c) && !(s[a] & s[b]) && !(s[b] & (s[a] << 1)) && !(s[b] & (s[a] >> 1))) {
f[i][j][a] += f[i-1][j - c][b];
}
}
}
}
}
cout << f[n + 1][k][0]; //这样子处理避免了还要累加的情况 在f在直接进行了
return 0;
}