hdu 5555 Immortality of Frog(状压dp)
2015-11-14 21:17
465 查看
题目链接:hdu 5555 Immortality of Frog
解题思路
因为每只青蛙最多碰到10个bad的membrane,所以可以用一个二进制状态表示到第i只青蛙还有哪些membrane可以选,但是二进制的状态的转移必须预处理,因为每只青蛙对应的bad membrane是不一样的。注意对于第i个位置来说,有membrane以这个位置终止,但是并没有被用掉则是非法的。剩下的good membrane就可以任意选了。代码
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 1050; const int mod = 105225319; int N, L[maxn], R[maxn]; int dp[maxn][maxn], G[maxn][maxn]; vector<int> B[maxn]; int find(int id, int x) { for (int i = 0; i < B[id].size(); i++) if (B[id][i] == x) return i; return -1; } bool init () { memset(G, 0, sizeof(G)); for (int i = 1; i < N; i++) { int n = B[i].size(), m = B[i+1].size(); if (n > 10) return false; for (int j = 0; j < m; j++) { int mv = find(i, B[i+1][j]); for (int s = 0; s < (1<<n); s++) { if (mv == -1 || (s&(1<<mv))) G[i][s] |= (1<<j); } } } for (int i = 1; i <= N; i++) { int n = B[i].size(); for (int s = 0; s < (1<<n); s++) { int c = 0; for (int j = 0; j < n; j++) { int v = B[i][j]; if (s&(1<<j) && R[v] == i) c++; } G[i][s] = (c ? -1 : G[i][s]); } } return B .size() <= 10;; } int solve (int k) { if (!init()) return 0; memset(dp, 0, sizeof(dp)); dp[1][(1<<B[1].size())-1] = 1; for (int i = 1; i <= N; i++) { int n = B[i].size(); for (int s = 0; s < (1<<n); s++) { if (dp[i][s] == 0) continue; for (int j = 0; j < n; j++) if (s&(1<<j)) { int v = G[i][s^(1<<j)]; if (v != -1) dp[i+1][v] = (dp[i+1][v] + dp[i][s]) % mod; } int u = G[i][s]; if (u != -1) dp[i+1][u] = (dp[i+1][u] + dp[i][s]) % mod; // printf("%d ", dp[i][s]); } // printf("\n"); } int ans = dp[N+1][0]; for (int i = 1; i <= k; i++) ans = (1LL * ans * i) % mod; return ans; } int main () { int cas; scanf("%d", &cas); for (int kcas = 1; kcas <= cas; kcas++) { scanf("%d", &N); for (int i = 1; i <= N; i++) scanf("%d", &L[i]); for (int i = 1; i <= N; i++) scanf("%d", &R[i]); int cnt = 0; for (int i = 1; i <= N; i++) B[i].clear(); for (int i = 1; i <= N; i++) if (R[i] - L[i] + 1 != N) { for (int j = L[i]; j <= R[i]; j++) B[j].push_back(i); cnt++; } printf("Case #%d: %d\n", kcas, solve(N - cnt)); } return 0; }
相关文章推荐
- Django配置Mysql数据库
- python复杂网络库networkx:基础
- 嵌入式底层软件开发学习系列之二计算机相关课程
- 九度OJ 1326:Waiting in Line(排队) (模拟)
- 基础知识系列5--五大查找(二叉查找树代码未写)
- 九度OJ 1326:Waiting in Line(排队) (模拟)
- linux 脚本积累
- Hibernate 错误
- 关于web性能的思考与分享[05]——gulp自动化构建工具入门教程
- C++数据结构: 链表
- 从技术经理的角度算一算,如何可以多快好省的做个App(一)
- 大道至简第七章第八章
- 使用复合键值对二次排序
- HDU 1847 Good Luck in CET-4 Everybody!(博弈入门)
- bzoj3339 Rmq Problem
- NOIP2015 总结&反思
- NSMutableString
- 大道至简第七八章阅读笔记
- django的HTTPREQUEST对象
- 微网站|h5弹窗|手机网站 html5 弹窗、弹层、提示框、加载条