八数码问题的初次解决(康托展开+bfs)
来源:互联网 发布:如何做淘宝卖家 编辑:程序博客网 时间:2024/06/04 23:21
八数码问题,常常是很多书上的例题,他作为一道经典的搜索题,被很多人誉为 不做过人生不完整,然而,对于这道题,实在是有太多高端的解法,然而我对于A*的理解还颇有偏差,于是选择了最普通的算法去完成这个问题,事实上,对于仅仅是八个数的题目来说,这道题目还是有很多方法可以解决的,下面我就简单的讲讲我做的那一种,而目前能力水平上的局限,希望能够在以后慢慢填补,下一次再用A*把这道题目做出来。
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 x where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle: 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8 9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12 13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x r-> d-> r-> The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, andfrustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by threearrangement.
Input
You will receive a description of a configuration of the 8 puzzle. The description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus ‘x’. For example, this puzzle
1 2 3 x 4 6 7 5 8 is described by this list: 1 2 3 x 4 6 7 5 8
Output
You will print to standard output either the word “unsolvable”, if the puzzle has no solution, or a string consisting entirely of the letters ‘r’, ‘l’, ‘u’ and ‘d’ that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line.
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
题目大意就是将八个数放在3*3的格子里,通过移动’X’的各自使他达到目标状态
解法:这题可以直接用BFS搜索,难度在于怎么标记状态,这里我们可以把X转化成0 在用康托展开,使得每一个数找到其对应的位置,这样就能用一个VIS 来标记。
#include <algorithm>#include <bitset>#include <cassert>#include <climits>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <deque>#include <iomanip>#include <iostream>#include <map>#include <numeric>#include <queue>#include <set>#include <stack>#include <string>#include <vector>#define inf 0x3f3f3f3f#define eps 1e-6using namespace std;typedef long long ll;using namespace std;const int dx[] = { -1,1,0,0 };const int dy[] = { 0,0,-1,1 };char op[] = { 'u','d','l','r' };typedef int state[9];struct node { state s; int d; int pre; char op;};node ei;vector<node>m;state goal;int vis[362880];int fact[9];void init() { fact[0] = 1; int i; for (i = 1; i < 9; i++) { fact[i] = fact[i - 1] * i; }}int try_to_insert(node t) { int code = 0; int i; for (i = 0; i<9; i++) { int cnt = 0; int j; for (j = i + 1; j<9; j++) if (t.s[j]<t.s[i])cnt++; code += fact[8 - i] * cnt; } if (vis[code])return 0; return vis[code] = 1;}node temp, cha;int bfs() { queue<node>q; ei.d = 0; ei.pre = -1; ei.op = '#'; q.push(ei); int z; while (!q.empty()) { temp = q.front(); m.push_back(temp); q.pop(); if (memcmp(goal, temp.s, sizeof(temp.s) == 0)) { return temp.d; } for (z = 0; z < 9; z++) { if (!temp.s[z]) break; } int x = z / 3, y = z % 3; int d; for (d = 0; d < 4; d++) { int newx = x + dx[d]; int newy = y + dy[d]; int newz = newx * 3 + newy; if (newx >= 0 && newx < 3 && newy >= 0 && newy < 3) { memcpy(cha.s, temp.s, sizeof(temp.s)); int t; t = cha.s[newz]; cha.s[z] = t; cha.s[newz] = 0; if (try_to_insert(cha) == 0)continue; cha.d = temp.d + 1; cha.pre = m.size() - 1; cha.op = op[d]; q.push(cha); if (memcmp(goal, cha.s, sizeof(cha.s)) == 0) { return cha.d; } } } } return 0;}char seq[1234567];int main() { init(); char a[9]; for (int i = 0; i < 9; i++) { goal[i] = i + 1; } goal[8] = 0; for (int i = 0; i < 9; i++) { cin >> a[i]; if (a[i] == 'x')ei.s[i] = 0; else ei.s[i] = a[i] - '0'; } if (bfs() == 0)printf("unsolvable\n"); else { int sn = 1, k; k = cha.pre; seq[0] = cha.op; while (m[k].pre != -1) { seq[sn++] = m[k].op; k = m[k].pre; } sn = sn - 1; int i; for (i = sn; i >= 0; i--) { cout << seq[i] ; } cout << endl; } return 0;}
- 八数码问题的初次解决(康托展开+bfs)
- hdu1043Eight (经典的八数码)(康托展开+BFS)
- hdu1043Eight (经典的八数码)(康托展开+BFS)
- 康托展开(八数码问题)
- 【康托展开+状压BFS】poj1077 Eight(八数码问题)
- POJ 1077 Eight 八数码问题[康托展开 + BFS]
- BFS+康托展开(洛谷1379 八数码难题)
- POJ 1077 八数码(康托展开+暴力bfs)
- hdu 1043 /poj 1077 Eight(经典八数码问题,BFS+康托展开)
- 蓝桥杯 历届试题 九宫重排 (八数码问题--康托展开去重 + bfs搜索)
- 康托展开求八数码问题
- poj 1077 bfs+康托展开(8数码问题)
- 八数码(康托展开)
- 八数码问题,bfs,hash,康托
- [POJ]1077 Eight 八数码:康托展开+BFS
- hdu 1043/poj 1077 Eight (八数码 经典搜索题 bfs + 康托展开)
- HDU1043BFS 康托展开 八数码
- HDU 1043 Eight (BFS·八数码·康托展开)
- 排序——交换排序之快速排序
- 大数乘法_字符串
- 从B 树、B+ 树、B* 树谈到R 树
- Zip
- Ecshop模板开发(十一):商品详情页用户购买记录
- 八数码问题的初次解决(康托展开+bfs)
- 缓存原理及优缺点
- First Missing Positive
- 1033. 旧键盘打字(20)
- 计算长方形的周长和面积(类和对象)
- 【C++学习笔记】类型组合
- C++实验4-输出星号图
- Leetcode-142. Linked List Cycle II
- 2016第七届蓝桥杯剪邮票