SCOI2005互不侵犯
基础版
按行转移
- 两个判断:
- 本集合(行)内是否冲突
- 不同行之间是否冲突(即是否互为八个方向之一)
- 动态转移方程
- 通过循环来实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; const int N = 15; int n, k; long long f[N][N * N][1 << N]; int size(int s) { int cnt = 0; for (; s; s >>= 1) { cnt += s & 1; } return cnt; } bool check(int s) { if (s & (s << 1)) return false; //本集合内国王是否冲突 return true; } bool check(int s, int t) { //两行之间的国王是否冲突 if ((t & s) || (s & (t << 1)) || ((s << 1) & t)) return false; return true; } int main() { ios::sync_with_stdio(false); cin >> n >> k; int m = 1 << n; f[0][0][0] = 1; //边界 //f[i][j][S]表示正在处理第i行,第i行放的格子集合为S,前i行共放了j个国王 for (int i = 1; i <= n + 1; i++) //行 for (int s = 0; s < m; s++) { // 枚举当前行的状态 if (check(s)) for (int t = 0; t < m; t++) { //枚举上一行的状态 if (check(t) && check(s, t)) { int sz = size(s); for (int j = sz; j <= k; j++) //国王个数 f[i][j][s] += f[i - 1][j - sz][t]; //由上一行转移来 } } } cout << f[n + 1][k][0]; }
(我再去研究下高级版怎么写(逃 )
满堂花醉三千客,一剑霜寒十四州
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步