hdu 1043 Eight
2015-02-19 15:36
351 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043
题目大意:给出魔方现在的状态:
2 3 4 1 5 x 7 6 8 ->
2 3 4
1 5 x
7 6 8
要求的魔方目的状态:
1 2 3
4 5 6
7 8 x
其中有4中操作:
(1) 2 3 4........2 3 x
......1 5 x...u->.1 5 4
......7 6 8........7 6 8
(2) 2 3 x........2 x 3
......1 5 4...l->.1 5 4
......7 6 8........7 6 8
(3) x 2 3........1 2 3
......1 5 4...d->.x 5 4
......7 6 8........7 6 8
(4) 1 2 3........1 2 3
......7 5 4...r->.7 5 4
......x 6 8........6 x 8
题目分析:反向搜索,从目标状态找回状态对应,将能到达的所有状态的路径保存下来,状态的表示用康托展开。
康托展开:X = an*(n-1)! + an-1*(n-2)! + …… + ai*(i-1)! + …… + a2*1! + a1*0!
其中ai表示比第i个数小的数字的个数(并且在前面没有出现过)
康托展开中排列中的数字没有重复的
例如:3 5 7 4 1 2 9 6 8(共9位数)
比3小的数都没有出现过,所以共有2个,以这样的数开始的排列有(9-1)!个,因此第一项为2 * 8!
比5小的数3出现过,所以共有3个,以这样的数开始的排列有(9-2)!个,因此第一项为3 * 7!
……
比8小的数都出现过,所以共有0个,以这样的数开始的排列有(9-9)!个,因此第一项为0
* 0!
所以,康托展开就为:X = 2 * 8! + 3 * 7! + 4 * 6! + 2 * 5! + 0 * 4! + 0 * 3! + 2 * 2! + 0 * 1! + 0 * 0! = 98884.
代码参考:
题目大意:给出魔方现在的状态:
2 3 4 1 5 x 7 6 8 ->
2 3 4
1 5 x
7 6 8
要求的魔方目的状态:
1 2 3
4 5 6
7 8 x
其中有4中操作:
(1) 2 3 4........2 3 x
......1 5 x...u->.1 5 4
......7 6 8........7 6 8
(2) 2 3 x........2 x 3
......1 5 4...l->.1 5 4
......7 6 8........7 6 8
(3) x 2 3........1 2 3
......1 5 4...d->.x 5 4
......7 6 8........7 6 8
(4) 1 2 3........1 2 3
......7 5 4...r->.7 5 4
......x 6 8........6 x 8
题目分析:反向搜索,从目标状态找回状态对应,将能到达的所有状态的路径保存下来,状态的表示用康托展开。
康托展开:X = an*(n-1)! + an-1*(n-2)! + …… + ai*(i-1)! + …… + a2*1! + a1*0!
其中ai表示比第i个数小的数字的个数(并且在前面没有出现过)
康托展开中排列中的数字没有重复的
例如:3 5 7 4 1 2 9 6 8(共9位数)
比3小的数都没有出现过,所以共有2个,以这样的数开始的排列有(9-1)!个,因此第一项为2 * 8!
比5小的数3出现过,所以共有3个,以这样的数开始的排列有(9-2)!个,因此第一项为3 * 7!
……
比8小的数都出现过,所以共有0个,以这样的数开始的排列有(9-9)!个,因此第一项为0
* 0!
所以,康托展开就为:X = 2 * 8! + 3 * 7! + 4 * 6! + 2 * 5! + 0 * 4! + 0 * 3! + 2 * 2! + 0 * 1! + 0 * 0! = 98884.
代码参考:
#include <queue> #include <cstdio> #include <string> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 1e6 + 9; //最多是9!/2 const int AIM = 46234; //12345670对应的康托展开的hash值 int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880}; //康拖展开判重 // 0! 1! 2! 3! 4! 5! 6! 7! 8! 9! int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//u,d,l,r char indexs[5]="durl";//和上面的要相反,因为是反向搜索 bool vis ; //标记 string path ; //记录路径 struct Node { int s[9]; int id, hashVal; string path; //路径 }puzzle; queue<Node> q; int cantor(int s[]) //康拖展开求该序列的hash值 { int sum = 0; for(int i = 0; i < 9; ++ i) { int num = 0; for(int j = i + 1; j < 9; ++ j) { if(s[j] < s[i]) num ++; } sum += (num * fac[9 - i - 1]); } return sum + 1; } void bfs(Node s) { q.push(s); path[AIM] = ""; while(!q.empty()) { Node head = q.front(); q.pop(); for(int i = 0; i < 4; ++ i) { int x = head.id / 3 + dir[i][0]; int y = head.id % 3 + dir[i][1]; if(x < 0 || x >= 3 || y < 0 || y >= 3) continue; Node t = head; t.id = x * 3 + y; t.s[head.id] = t.s[t.id]; t.s[t.id] = 0; t.hashVal = cantor(t.s); if(!vis[t.hashVal]) { vis[t.hashVal] = 1; //此状态可达 t.path = indexs[i] + t.path; //因为是逆序,当前这步+之前的路径 q.push(t); path[t.hashVal] = t.path; } } } } int main() { char ch; Node start; //起点即为目标序列 for(int i = 0; i < 8; ++ i) { start.s[i] = i + 1; } start.s[8] = 0; start.id = 8; start.hashVal = AIM; start.path = ""; bfs(start); while(cin >> ch) { if(ch == 'x') { puzzle.s[0] = 0; puzzle.id = 0; } else { puzzle.s[0] = ch - '0'; } for(int i = 1; i < 9; ++ i) { cin >> ch; if(ch == 'x') { puzzle.s[i] = 0; puzzle.id = i; } else puzzle.s[i] = ch - '0'; } puzzle.hashVal = cantor(puzzle.s); //获取输入序列的hash值 if(vis[puzzle.hashVal]) { cout<<path[puzzle.hashVal]<<endl; } else { puts("unsolvable"); } } return 0; }
相关文章推荐
- [HDU 1043] Eight A*或IDA*
- HDU 1043 Eight
- POJ-1077 HDU-1043 Eight(单广,双广,启发式搜索)
- hdu1043 Eight(A*/双向BFS/单项BFS打表+康托展开)
- hdu 1043 Eight(BFS经典)
- hdu 1043 Eight 双向BFS/A*算法
- HDU 1043 Eight(广搜+哈希+康托展开+打表)
- hdu 1043 Eight(8数码,第三重)
- HDU-1043 Eight
- HDU 1043 Eight 反向BFS
- 【hdu 1043】Eight
- hdu 1043 Eight 经典八数码问题
- eight(hdu-1043)(待修正)
- HDU 1043 Eight (BFS·八数码·康托展开)
- HDU1043_Eight_A*算法&康托展开
- POJ 1077 HDU 1043 Eight (IDA*)
- HDU 1043 Eight 八数码问题 A*搜索 启发式算法
- HDU 1043 Eight(反向BFS打表+康托展开)
- POJ1077&HDU1043 Eight 八数码第七境界 AStar hash 康托展开 最小堆优化 奇偶剪枝
- POJ1077&HDU1043 Eight 八数码第八境界 IDA* hash 康托展开 奇偶剪枝