HDU 1043 && POJ 1077 Eight (A*)
2015-09-07 13:08
519 查看
题目链接:HDU 1043
POJ 1077
解析:A*算法
搜索中选择路径的条件:f = g + h
g:搜索深度
h:当前状态所有格点与目标状态对应格点曼哈顿距离。(曼哈顿距离:横纵坐标差值的绝对值之和)
中间还有一个剪枝:只有起始状态和目标状态的奇偶性相同时,才有解,否则,直接输出无解。
AC代码:
POJ 1077
解析:A*算法
搜索中选择路径的条件:f = g + h
g:搜索深度
h:当前状态所有格点与目标状态对应格点曼哈顿距离。(曼哈顿距离:横纵坐标差值的绝对值之和)
中间还有一个剪枝:只有起始状态和目标状态的奇偶性相同时,才有解,否则,直接输出无解。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <algorithm> #include <stack> using namespace std; int pos[][2] = {0, 0, 0, 1, 0, 2, 1, 0, 1, 1, 1, 2, 2, 0, 2, 1, 2, 2}; int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320}; //hash值,康托展开的结果 int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; char to_s[5] = "durl"; struct Node{ char mz[3][3]; int x, y; int g, h, f; friend bool operator <(const Node& a, const Node& b){ if(a.f == b.f) return a.g < b.g; return a.f > b.f; } }; Node start; int _hash(Node a){ char s[10]; int ans = 0; for(int i=0; i<3; i++) for(int j=0; j<3; j++){ s[i*3+j] = a.mz[i][j]; int cnt = 0; for(int k=i*3+j-1; k>=0; k--) if(s[k] > s[i*3+j]) cnt ++; ans += fac[i*3+j] * cnt; } return ans; } int h(Node a){ int ans = 0; for(int i=0; i<3; i++) for(int j=0; j<3; j++) { if(a.mz[i][j] == 'x') continue; int k = a.mz[i][j] - '1'; ans += abs(pos[k][0] - i) + abs(pos[k][1] - j); } return ans; } bool ok(){ //检查起始状态与目标状态的逆序数的奇偶性是否一致 char a[10]; int cnt = 0; for(int i=0; i<3; i++){ for(int j=0; j<3; j++){ a[i*3+j] = start.mz[i][j]; if(a[i*3+j] == 'x') continue; for(int k=i*3+j-1; k>=0; k--){ if(a[k] == 'x') continue; if(a[k] > a[i*3+j]) cnt ++; } } } return cnt % 2 == 0; //由于目标状态的逆序数是偶数 } char str[100], op[363000]; int pre[363000]; bool flag[363000]; void Astar(){ //A*算法 memset(flag, false, sizeof(flag)); priority_queue<Node> q; q.push(start); while(!q.empty()){ Node now = q.top(); q.pop(); int hnow = _hash(now); for(int i=0; i<4; i++){ Node tp = now; tp.x += dir[i][0]; tp.y += dir[i][1]; if(tp.x < 0 || tp.y < 0 || tp.x >= 3 || tp.y >= 3) continue; tp.mz[now.x][now.y] = now.mz[tp.x][tp.y]; tp.mz[tp.x][tp.y] = 'x'; tp.g ++; tp.h = h(tp); tp.f = tp.g + tp.h; int htp = _hash(tp); if(flag[htp]) continue; flag[htp] = true; pre[htp] = hnow; op[htp] = to_s[i]; if(htp == 0) return ; q.push(tp); } } } void print(){ int hstart = _hash(start); int cur = 0; stack<char> p; while(hstart != cur){ p.push(op[cur]); cur = pre[cur]; } while(!p.empty()){ putchar(p.top()); p.pop(); } puts(""); } int main(){ #ifdef sxk freopen("in.txt", "r", stdin); #endif // sxk while(gets(str)){ int x = 0, y = 0; int len = strlen(str); for(int i=0; i<len; i++){ if(str[i] >= '0' && str[i] <= '9' || str[i] == 'x'){ start.mz[x][y] = str[i]; if(str[i] == 'x'){ start.x = x; start.y = y; } y ++; if(y == 3){ x ++; y = 0; } } } if(!ok()){ puts("unsolvable"); continue; } start.g = 0; start.h = h(start); start.f = start.h; if(_hash(start) == 0){ puts(""); continue; } Astar(); print(); } return 0; }
相关文章推荐
- 隐藏键盘的几种方法
- hdu 5000
- Java中sleep(),wait(),yield()的区别
- 代理服务器的学习
- hdu 5000
- Android ListView滑动过程中控件显示重复/错误问题之原理分析及解决方案
- 设计模式-单例模式
- [LeetCode] Missing Ranges
- 使用Beep()函数发出指定音高 (一)
- 动态规划求解抛鸡蛋问题(Google某年面试题)
- 【PI】配件论坛
- Android数据存储之SharePreference
- NYOJ_97 兄弟郊游问题
- OAF学习笔记-18- Update后页面显示不是最新的数据的解决方法
- OAF学习笔记-18- Update后页面显示不是最新的数据的解决方法
- OAF学习笔记-18- Update后页面显示不是最新的数据的解决方法
- OAF学习笔记-18- Update后页面显示不是最新的数据的解决方法
- OAF学习笔记-18- Update后页面显示不是最新的数据的解决方法
- OAF学习笔记-18- Update后页面显示不是最新的数据的解决方法
- OAF学习笔记-18- Update后页面显示不是最新的数据的解决方法