You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
typedef long long LL;
|
|
|
|
|
const int N = 11; //棋盘的长宽上限
|
|
|
|
|
const int M = 1 << 10; //二进制枚举的状态数量上限,因为n最大是10,就是2^10个状态
|
|
|
|
|
const int K = 110; //国王的个数上限
|
|
|
|
|
int n; //n*n的棋盘
|
|
|
|
|
int m; //国王的数量
|
|
|
|
|
vector<int> st; //所有合法的状态(预处理的结果)
|
|
|
|
|
vector<int> head[M]; //某个状态兼容哪些状态(预处理的结果)
|
|
|
|
|
int cnt[M]; //记录每种状态中的数字1个数,了解本行使用了多少个国王
|
|
|
|
|
//完成前i行,使用了j个国王,现在的状态是k:001010111之类,存在的是二进制对应的十进制数
|
|
|
|
|
LL f[N][K][M];
|
|
|
|
|
|
|
|
|
|
//判断一行是不是有连续1
|
|
|
|
|
bool check(int x) {
|
|
|
|
|
return !(x & x >> 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//统计某个状态中数字1的数量
|
|
|
|
|
int count(int x) {
|
|
|
|
|
int res = 0;
|
|
|
|
|
for (int i = 0; i < 32; i++) res += x >> i & 1;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
cin >> n >> m;
|
|
|
|
|
//1、可行的合法状态预处理
|
|
|
|
|
for (int i = 0; i < 1 << n; i++)
|
|
|
|
|
if (check(i)) st.push_back(i), cnt[i] = count(i);
|
|
|
|
|
|
|
|
|
|
//i与i-1行之间的兼容关系记录下来
|
|
|
|
|
for (int a: st)
|
|
|
|
|
for (int b: st)
|
|
|
|
|
//a&b==0:同列不是同时为1,表示列上面国王不冲突
|
|
|
|
|
//check(a|b): 经或处理后的数字,如果存在连续的1,就表示斜45度有国王,不合法,妙不可言
|
|
|
|
|
if ((a & b) == 0 && check(a | b)) head[a].push_back(b);//记录合法的状态转移关系
|
|
|
|
|
|
|
|
|
|
//2、DP
|
|
|
|
|
//已经摆完了前0行,放置了0个国王,当前状态全是0,这种情况下只有全是0的状态是合法的,方案数为0.
|
|
|
|
|
f[0][0][0] = 1;
|
|
|
|
|
for (int i = 1; i <= n; i++) //枚举每一行
|
|
|
|
|
for (int j = 0; j <= m; j++) //枚举国王个数
|
|
|
|
|
for (int a: st) { //枚举第i行的每一种可能状态
|
|
|
|
|
for (int b: head[a]) { //s状态与哪些状态兼容
|
|
|
|
|
int c = cnt[a]; //状态st[s]的国王数量也可以一并预处理出来,当然也可以现用现算
|
|
|
|
|
//上面的j循环,限定了国王的数量上限
|
|
|
|
|
if (j >= c) f[i][j][a] += f[i - 1][j - c][b];//从上一层的状态转化而来
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//结果
|
|
|
|
|
LL ans = 0;
|
|
|
|
|
//在填充完n行之后,将m个国王放完,每一个合法状态都是可能的解,需要累加起来才是答案
|
|
|
|
|
for (int a: st) ans += f[n][m][a];
|
|
|
|
|
printf("%lld", ans);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|