AcWing 1064. 小国王
状态:f[i][j][k]
表示第i
行放了j
个皇帝,状态为k
的方案。
那么首先预处理出所有可行的方案,以及两两可以相互转移的答案。
从b
状态转移到a
状态就是 :
小tips:
判断两行有没有相邻的一可以判断: ,一定要加括号,判断当两个在前后两行的皇帝是否能斜着攻击到:即不能有相邻的1
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 15, M = 110, K = 1 << 10;
LL f[N][M][K]; //第i行 放了j个皇帝 状态为k的方案集合
int n, m;
vector<int> legal;
int cnt[K + 10];
vector<int> head[K];
bool check(int num) { //没有相邻
for (int i = 0; i < n; i++) {
if ((num >> i & 1) && ((num >> i + 1) & 1)) return false;
}
return true;
}
int count(int num) {
int cnt = 0;
while (num) num -= (num & -num), cnt++;
return cnt;
}
int main() {
cin >> n >> m;
for (int i = 0; i < 1 << n; i++) {
if (check(i)) {
legal.push_back(i);
cnt[i] = count(i);
}
}
for (int i = 0; i < legal.size(); i++) {
for (int j = 0; j < legal.size(); j++) {
int a = legal[j], b = legal[i];
if ((a & b) == 0 && check(a | b))
head[i].push_back(j); //由j可以转移到i
}
}
f[0][0][0] = 1;
for (int i = 1; i <= n; i++) { //枚举行
for (int j = 0; j <= m; j++) { //枚举有多少个皇帝
for (int a = 0; a < legal.size(); a++) { //枚举可转移的状态
for (int b = 0; b < head[a].size(); b++) {
int c = cnt[legal[a]];
if (j >= c) f[i][j][a] += f[i - 1][j - c][head[a][b]];
}
}
}
}
LL res = 0;
for (int i = 0; i < 1 << 10; i++) res += f[n][m][i];
cout << res << endl;
//cout << f[n + 1][m][0] << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端