[hdu 6171 Admiral]Hash+暴搜+中途相遇法
来源:互联网 发布:瑞特优化 编辑:程序博客网 时间:2024/05/18 03:10
[hdu 6171 Admiral]Hash+暴搜+中途相遇法
分类:meet in middle
brute force
Hash
1. 题目链接
[hdu 6171 Admiral]
2. 题意描述
给你一个高度为6的数塔,问最少多少步能走成如下状态。大于20步可以直接输出“too difficult”!
每次只能将值为0的点与其左上,上方,下方,右下四个方向的一个点进行交换。
0
1 1
2 2 2
3 3 3 3
4 4 4 4 4
5 5 5 5 5 5
3. 解题思路
很裸的暴搜+Hash。对每一个状态朝四个方向进行暴搜。
如果不用meet in middle
方法 理论上暴搜的状态数和复杂度会爆炸。
对于“固定源点和端点的条件下,求
t 步之内是否可以从源点达到端点,如果能,求出最短步数。”的这类问题,一般都可以用meet in middle
的方法来解决。
meet in middle
:枚举分别从源点、端点开始走t2 步,记录到达中间所有的状态需要的最短步数。然后,求出源点、端点走t2 步能够达到的公共状态。对于所有公共状态,源点到公共状态的步数+端点到公共状态的步数的最小值就是从源点到端点所需要的最短步数。
4. 实现代码
#include <bits/stdc++.h>using namespace std;typedef long long LL;typedef long double LB;typedef unsigned int uint;typedef unsigned long long ULL;typedef pair<int, int> PII;typedef pair<int, LL> PIL;typedef pair<LL, LL> PLL;typedef pair<LB, LB> PLB;typedef vector<int> VI;const int INF = 0x3f3f3f3f;const LL INFL = 0x3f3f3f3f3f3f3f3fLL;const long double PI = acos(-1.0);const long double eps = 1e-4;void debug() { cout << endl; }template<typename T, typename ...R> void debug (T f, R ...r) { cout << "[" << f << "]"; debug (r...); }template<typename T> inline void umax(T &a, T b) { a = max(a, b); }template<typename T> inline void umin(T &a, T b) { a = min(a, b); }template <typename T> inline bool scan_d (T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; //EOF while (c != '-' && (c < '0' || c > '9') ) if((c = getchar()) == EOF) return 0; sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1;}template<typename T> void print(T x) { static char s[33], *s1; s1 = s; if (!x) *s1++ = '0'; if (x < 0) putchar('-'), x = -x; while(x) *s1++ = (x % 10 + '0'), x /= 10; while(s1-- != s) putchar(*s1);}template<typename T> void println(T x) { print(x); putchar('\n'); }template<typename T> T randIntv(T a, T b) { return rand() % (b - a + 1) + a; } /*[a, b]*/struct Node { static const int MAXB = 6; static const int MAXL = 21; int d[MAXB][MAXB]; LL getHashV() { LL ret = 0; for(int i = 0; i < MAXB; ++i) { for(int j = 0; j <= i; ++j) { ret += d[i][j]; ret *= MAXB; } } return ret; } static PII getHashD(LL hv, Node& e) { static int b[MAXL]; int k = MAXL; while(k >= 0) { b[-- k] = hv % MAXB; hv /= MAXB; } PII ret(-1, -1); for(int i = 0; i < MAXB; ++i) { for(int j = 0; j <= i; ++j) { e.d[i][j] = b[k ++]; if(e.d[i][j] == 0) ret = make_pair(i, j); } } return ret; } void P() { for(int i = 0; i < Node::MAXB; ++i) { for(int j = 0; j <= i; ++j) { print(d[i][j]); putchar(' '); } putchar('\n'); } }} S, E, O;int T;int dx[] = { -1, -1, 1, 1};int dy[] = { -1, 0, 0, 1};inline bool okay(const int& x, const int& y) { return 0 <= x && x < Node::MAXB && 0 <= y && y <= x; }map<LL, int> mp1, mp2;map<LL, int>::iterator it;void bfs(map<LL, int>& mp, Node& u, const int& mstep) { typedef PIL QNode; queue<QNode> q; int x, y, step = 0, mpv; LL hashV = u.getHashV(); mp.clear(); mp[hashV] = 0; q.push(QNode(step, hashV)); while(!q.empty()) { tie(step, hashV) = q.front(); q.pop(); if(step > mstep) continue; mpv = mp[hashV]; if(mpv != 0 && mpv <= step) continue; mp[hashV] = step; tie(x, y) = Node::getHashD(hashV, O); for(int i = 0; i < 4; ++i) { int nx = x + dx[i], ny = y + dy[i]; if(!okay(nx, ny)) continue; swap(O.d[x][y], O.d[nx][ny]); hashV = O.getHashV(); q.push(QNode(step + 1, hashV)); swap(O.d[x][y], O.d[nx][ny]); } }}int main() {#ifdef ___LOCAL_WONZY___ freopen ("input.txt", "r", stdin);#endif // ___LOCAL_WONZY___ scan_d(T); for(int i = 0; i < Node::MAXB; ++i) { for(int j = 0; j <= i; ++j) { E.d[i][j] = i; } } bfs(mp1, E, 10); /** mp1.size() == 4034 **/ while(T --) { for(int i = 0; i < Node::MAXB; ++i) { for(int j = 0; j <= i; ++j) { scan_d(S.d[i][j]); } } bfs(mp2, S, 10); int ans = 21; if(S.getHashV() == E.getHashV()) ans = 0; for(it = mp2.begin(); it != mp2.end(); ++it) { int s1 = mp1[it->first], s2 = it->second; if(s1 == 0 || s1 + s2 >= ans) continue; ans = s1 + s2; } if(ans == 21) puts("too difficult"); else println(ans), assert(ans <= 20); }#ifdef ___LOCAL_WONZY___ cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // ___LOCAL_WONZY___ return 0;}
阅读全文
1 0
- [hdu 6171 Admiral]Hash+暴搜+中途相遇法
- UVa 10125 - Sumsets (中途相遇法 hash)
- HDU 6171 Admiral [双向bfs+hash]
- hdu 6171 Admiral 双向bfs+hash
- Uva10125/POJ2549——Sumsets(中途相遇法,hash)
- uva10125 (中途相遇法)
- 中途相遇法
- HDU-4963 Dividing a String (枚举[中途相遇法])
- poj3977 Subset 中途相遇法...
- UvaLive 2965 中途相遇法
- HDU5936 Difference 【中途相遇法】
- poj 1903 中途相遇法
- 【多校训练】hdu 6171 Admiral 双向bfs+hash
- BAPC2014 K题 Key to Knowledge(中途相遇法,hash,状态压缩)
- POJ #1186 方程的解数 | 中途相遇法 + Hash | 解题报告
- HDU 6171 Admiral
- Jurassic Remains,NEERC 2003,中途相遇法
- uva 1326 Jurassic Remains(中途相遇法)
- POJ
- 整理:C/C++可变参数,“## __VA_ARGS__”宏的介绍和使用
- Python字典的操作
- 基于TensorFlow的车牌号识别系统
- 并查集详解 (转)
- [hdu 6171 Admiral]Hash+暴搜+中途相遇法
- zookeeper分布式锁以及集群
- 华为USG6300系列防火墙 多公网IP端口映射
- 面向对象三大特性之多态
- 快速素数筛模板
- jquery中的ajax方法
- 排序大乱斗
- KNN算法---Python实现
- 替换空格java实现