hdu 5440 Clock Adjusting(双向bfs)
来源:互联网 发布:装饰公司网络销售 编辑:程序博客网 时间:2024/06/05 20:56
题目链接:hdu 5440 Clock Adjusting
解题思路
卡着时间AC的,双向bfs,根据指向1,2…,12的clock个数建立hash函数,从终止状态逆向搜索5步,从起始状态正向搜索3步(因为终止状态对应的都是12,所以转移起来状态相对起始状态要少一些)
使用tool的顺序是无关紧要的,所以在搜索时,考虑到状态s,是通过使用前i个tool转移过来的,那么只需要在考虑使用i,i+1…,M即可(这里我优先使用编号大的tool,不确定有没有优化的作用)
在确定状态s和工具i后,需要枚举修改哪些clock,一开始我是用二进制状态表示需要被修改的地方,但是重复的太多,就用dfs+剪枝枚举。
这题应该还有更厉害的优化,我是卡1400Ms过的。
代码
#include <cstdio>#include <cstring>#include <set>#include <map>#include <vector>#include <queue>#include <algorithm>using namespace std;typedef long long ll;const int maxn = 1 * 1e5 + 5;ll S;int N, M, L[10], X[10], head, rear, ans;map<ll, int> C;set<ll> T;struct State { ll s; int f, c; State(ll s = 0, int f = 0, int c = 0): s(s), f(f), c(c) {}}Q[maxn], cur;inline ll idx(int* c) { ll ret = 0; for (int i = 0; i < 12; i++) ret = ret * (N+1) + c[i]; return ret;}inline void reidx(ll s, int* c) { for (int i = 11; i >= 0; i--) { c[i] = s % (N+1); s /= (N+1); }}void init () { C.clear(); T.clear(); scanf("%d%d", &N, &M); int x, cnt[15]; memset(cnt, 0, sizeof(cnt)); for (int i = 1; i <= N; i++) { scanf("%d", &x); if (x == 12) x = 0; cnt[x]++; } S = idx(cnt); for (int i = 0; i < M; i++) scanf("%d%d", &L[i], &X[i]);}bool dfs1 (int d, int* c, int* t, int n, int m, int v) { if (d > 12 || n > m) return false; if (n == 0 && m == 0) { ll tmp = idx(t); if (tmp == S) { ans = cur.c + 1; return true; } if (!C.count(tmp)) { C[tmp] = cur.c + 1; if (cur.c < 4) Q[rear++] = State(tmp, v, cur.c+1); } return false; } for (int i = min(c[d], n); i >= 0; i--) { if (n-i > m-c[d]) break; t[(d-X[v]+12)%12] += i; t[d] += (c[d] - i); if (dfs1(d+1, c, t, n-i, m-c[d], v)) return true; t[(d-X[v]+12)%12] -= i; t[d] -= (c[d] - i); } return false;}bool dfs2 (int d, int* c, int* t, int n, int m, int v) { if (d > 12 || n > m) return false; if (n == 0 && m == 0) { ll tmp = idx(t); if (C.count(tmp)) { ans = C[tmp] + cur.c + 1; return true; } if (!T.count(tmp) && cur.c < 2) { T.insert(tmp); Q[rear++] = State(tmp, v, cur.c+1); } return false; } for (int i = min(c[d], n); i >= 0; i--) { if (n-i > m-c[d]) break; t[(d+X[v]+12)%12] += i; t[d] += (c[d] - i); if (dfs2(d+1, c, t, n-i, m-c[d], v)) return true; t[(d+X[v]+12)%12] -= i; t[d] -= (c[d] - i); } return false;}int bfs() { int cnt[15], pos[15]; memset(cnt, 0, sizeof(cnt)); cnt[0] = N; ll k = idx(cnt); if (S == k) return 0; C[k] = 0; head = rear = 0; for (int i = 0; i < M; i++) { int x = (-X[i] + 12) % 12; cnt[x] += L[i]; cnt[0] -= L[i]; ll tmp = idx(cnt); if (!C.count(tmp)) { if (tmp == S) return 1; Q[rear++] = State(tmp, i, 1); C[tmp] = 1; } cnt[x] -= L[i]; cnt[0] += L[i]; } while (head < rear) { cur = Q[head++]; reidx(cur.s, cnt); for (int i = M-1; i >= cur.f; i--) { memset(pos, 0, sizeof(pos)); if (dfs1(0, cnt, pos, L[i], N, i)) return ans; } } head = rear = 0; Q[rear++] = State(S, 0, 0); while (head < rear) { cur = Q[head++]; reidx(cur.s, cnt); for (int i = M-1; i >= cur.f; i--) { memset(pos, 0, sizeof(pos)); if (dfs2(0, cnt, pos, L[i], N, i)) return ans; } } return -1;}int main () { int cas; scanf("%d", &cas); while (cas--) { init(); printf("%d\n", bfs()); } return 0;}
0 0
- hdu 5440 Clock Adjusting(双向bfs)
- hdu-3085(双向bfs)
- HDU 1401 Solitaire(双向BFS)
- hdu 3085 Nightmare Ⅱ (双向bfs)
- hdu 1401 Solitaire(双向bfs)
- HDU-#1372 Knight Moves(双向BFS)
- HDU 3081 Nightmare Ⅱ(双向BFS)
- hdu 1401 双向搜索(bfs)
- HDU 3085 Nightmare Ⅱ(双向BFS)
- HDU 3085 Nightmare Ⅱ(双向BFS)
- HDU-1915-Knight Moves(双向BFS)
- hdu 1401 双向bfs
- hdu 3085 双向BFS
- hdu 3085(双向bfs)
- hdu 1195 双向bfs
- HDU 1560 双向BFS
- HDU 3085 双向BFS
- HDU 1401 双向BFS !!!
- 【IOS 开发学习总结-OC-26】★★★objective-c——foundation 框架之日期与时间
- HTTP协议简述
- 深入了解scanf/getchar/gets/cin等函数
- 版本控制工具(CVS、SVN、GIT)简介
- NYOJ 904 search
- hdu 5440 Clock Adjusting(双向bfs)
- Swift学习- 下标脚本(十二)
- 二分查找
- HashMap与HashTable面试宝典
- [c++]无锁队列
- POJ 3984:迷宫问题 bfs+递归输出路径
- 解题报告 之 ZOJ 3829 Known Notation
- C语言实现的猜数字小游戏(主要是对于自定义函数的运用)
- ip转换为纯数字(如何用数字表示ip?)