ACwing1064. 小国王
线性状压DP
#include <iostream> #include <stdio.h> #include <algorithm> #include <string> #include <cmath> #include <vector> #define R(x) x = read() #define For(i, j, n) for (int i = j; i <= n; ++i) using namespace std; const int N = 15, K = 105, M = 1 << 10; typedef long long LL; int n, k; vector<int> LegalStates; vector<int> Transformation[M]; inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } inline int lowbit(int x) { return x & (-x); } int cnt[M]; bool check(int a, int b) { if (a & b) return 1; int t = a | b; if (t & (t >> 1)) return 1; return 0; } void init() { for (int i = 0; i < (1 << n); i++) { if (i & (i >> 1)) continue; LegalStates.push_back(i); int t = i; while (t) { cnt[i]++; t -= lowbit(t); } } // Transformation.resize((1 << n), vector<int>(0, 0)); for (int a : LegalStates) { for (int j : LegalStates) { if (!check(a, j)) Transformation[a].push_back(j); } } } LL f[2][K][M]; LL dp() // 答案会爆int,结果f数组改成long long之后dp函数忘记由int改为long long了,八嘎 { f[0][0][0] = 1ll; for (int i = 1; i <= n + 1; i++) for (int st : LegalStates) { for (int c = cnt[st]; c <= k; c++) { f[i & 1][c][st] = 0; //采用滚动数组,这里记得要先清零,否则会重复在同一个位置多次累加,导致答案偏大 int lc = c - cnt[st]; for (int j : Transformation[st]) f[i & 1][c][st] += f[(i - 1) & 1][lc][j]; } } return f[(n + 1) & 1][k][0]; } int main() { R(n); R(k); init(); /*for(int i : LegalStates) { cout << i << " " << cnt[i] << endl; cout << "K:"; for(int j : Transformation[i]) cout << j << " "; cout << endl; }*/ printf("%lld\n", dp()); return 0; }
本文作者:smartljy
本文链接:https://www.cnblogs.com/smartljy/p/18109201
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步