康托展开求八数码问题
2015-01-09 16:49
381 查看
/* 问题描述: 目标状态为: 1 2 3 4 5 6 7 8 0 输入初始状态,求初始状态到最终状态的路径分别 用u(向上),d(向下),l(向左),r(向右)来表示四个方向的移动; 如果有解,则输出路径,否则输出"unsolvable" 有多个输入 */ #include<iostream> #include<queue> #include<string> #include<cstring> using namespace std; long long fac[10] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 }; const int direction[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; //0移动的方向 bool closeList[362880 + 10]; //记录一个节点是否被访问过 // l , r, u, d char action[5] = "udlr"; //移动的步骤,对应上面的direction int target = 0; //保存目标状态的康托展开值 int tmptarget[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 }; //目标状态 const int num = 3; struct Node{ int state[num * num]; int zero; //0的位置 string steps; //从初始节点到当前节点的路径 int cnt; //当前状态的康托展开值 }; //康托展开 int Cantor(int state[9]){ int id = 0; for (size_t i = 0; i < num * num; i++){ int count = 0; for (size_t j = i + 1; j < num * num; j++){ if (state[i] > state[j]) count++; } id += (count * fac[num * num - i - 1]); } return id + 1; } int main(int argc, char *argv[]){ target = Cantor(tmptarget); char ch; //1 2 3 4 5 x 7 8 6 //2 3 4 1 5 x 7 6 8 while (cin >> ch){ //记得把cin >> ch放在这里,否则会time limit Node head; Node next; if (ch == 'x'){ head.zero = 0; head.state[0] = 0; } else head.state[0] = ch - '0'; for (int i = 1; i < num * num; i++){ cin >> ch; //输入起始状态 if (ch == 'x'){ //把x换成0 head.zero = i; head.state[i] = 0; } else head.state[i] = ch - '0'; } head.cnt = Cantor(head.state); head.steps = ""; queue<Node> openList; bool flag = false; //记录是否达到目标状态 string path = ""; //记录从起始节点到目标节点的路径 memset(closeList, false, sizeof(closeList)); openList.push(head); while (!openList.empty() && !flag){ head = openList.front(); if (head.cnt == target){ //判断是否达到目标状态 flag = true; path = head.steps; break; } int oldr = head.zero / num; //0所在的行 int oldc = head.zero % num; //0所在的列 for (int i = 0; i < 4; i++){ int newr = oldr + direction[i][0]; int newc = oldc + direction[i][1]; if (newr >= 0 && newr < num && newc >= 0 && newc < num){ next = head; next.zero = newr * 3 + newc; //0的新位置 next.state[head.zero] = head.state[next.zero]; next.state[next.zero] = 0; next.cnt = Cantor(next.state); if (!closeList[next.cnt]){ next.steps = head.steps + action[i]; if (next.cnt == target){ flag = true; path = next.steps; break; } closeList[next.cnt] = true; openList.push(next); } } } openList.pop(); } if (flag){ //找到解,输出路径 cout << path << "\n"; } else{ cout << "unsolvable" << "\n"; } } return 0; }
相关文章推荐
- 蓝桥杯 历届试题 九宫重排 (八数码问题--康托展开去重 + bfs搜索)
- 康托展开与八数码问题
- 【康托展开+状压BFS】poj1077 Eight(八数码问题)
- UVA 10085(bfs+康拓展开)八数码问题
- 康托展开、逆展开、魔板问题
- 八数码问题,bfs,hash,康托
- permutation 问题小结——康托展开
- 康托展开和康托逆展开解决第K个排列问题
- HDOJ 1043 八数码问题(经典题) bfs+托康展开
- PKU1077 八数码,双向广搜+康托展开
- POJ 1077八数码问题(cantor展开+BFS)
- poj 1077 Eight 八数码问题( 康拓展开+BFS状态压缩)
- HDU 1043 八数码问题 A*搜索+康拓展开+逆序对判断+路径输出
- A*算法在八数码问题上的应用
- 八数码问题的 A* 算法解答
- ASP.NET应用程序中TreeView 控件 即需填充 TreeNode 数据时,节点展开问题
- 八数码问题
- 八数码问题分析
- 八数码问题——A*搜索
- 康托展开