题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 , 康托展开 + BFS + 打表。
经典八数码问题,传说此题不做人生不完整,关于八数码的八境界:http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html
我自己是用哈希(康托展开) + BFS + 打表过的,第三重境界。
由于一些高级的搜索现在还没学,所以目前能升级的也就是用双向BFS来做了,等过几天有心情了来做。
本文长期更新。
算法:
由于此题是求某个起始状态到“12345678X”的步骤,所以可以考虑先求出“12345678X”的所有变换的步骤,即打表预处理。
这里要注意就是最后输出的时候,由于我们求得是逆序,所以要倒序输出,倒序输出的时候要注意'u'、'd'、'l'、'r'都应该颠倒过来,比如说你从A状态向上变换为B状态,这时你从B变为A就要向下变换。
这里哈希还是用的康托展开,这个问题我在上一篇博客中有提到过。
BFS + 打表:
#include <iostream> #include <cstdio> #include <vector> #include <queue> #include <cmath> #include <string> #include <string.h> #include <algorithm> using namespace std; #define LL __int64 #define eps 1e-8 #define INF 1e8 #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int MOD = 2333333; const int maxn = 362880; bool vis[maxn]; string ans[maxn]; int fac[]={1 , 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320 , 362880}; int Cantor(string str) { int ret = 0; int n = str.size(); for(int i = 0 ; i < n ; i++) { int cnt = 0; for(int j = i ; j < n ; j++) if(str[j] < str[i]) cnt++; ret += cnt * fac[n - i - 1]; } return ret; } void move_Up(string &str , int pos) { swap(str[pos] , str[pos - 3]); } void move_Down(string &str , int pos) { swap(str[pos] , str[pos + 3]); } void move_Left(string &str , int pos) { swap(str[pos] , str[pos - 1]); } void move_Right(string &str , int pos) { swap(str[pos] , str[pos + 1]); } void BFS(string start) { memset(vis , 0 , sizeof(vis)); queue <string> que; que.push(start); int x = Cantor(start); vis[x] = 1; ans[x] = ""; int pos; while(!que.empty()) { string u = que.front(); que.pop(); int i = Cantor(u); for(pos = 0 ; pos < 9 ; pos++) if(u[pos] == 'x') break; if(pos > 2) { string tmp = u; move_Up(tmp , pos); int k = Cantor(tmp); if(!vis[k]) { vis[k] = 1; que.push(tmp); ans[k] = ans[i] + 'u'; } } if(pos < 6) { string tmp = u; move_Down(tmp , pos); int k = Cantor(tmp); if(!vis[k]) { vis[k] = 1; que.push(tmp); ans[k] = ans[i] + 'd'; } } if(pos % 3 != 0) { string tmp = u; move_Left(tmp , pos); int k = Cantor(tmp); if(!vis[k]) { vis[k] = 1; que.push(tmp); ans[k] = ans[i] + 'l'; } } if(pos % 3 != 2) { string tmp = u; move_Right(tmp , pos); int k = Cantor(tmp); if(!vis[k]) { vis[k] = 1; que.push(tmp); ans[k] = ans[i] + 'r'; } } } } int main() { char ch[30]; string start = "12345678x"; BFS(start); while(gets(ch)) { string str = ""; for(int i = 0 ; ch[i] != '