八数码块

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, and 
frustrating 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 three 
arrangement.

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

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #define MAXN 500000
  5 using namespace std;
  6 char input[30];
  7 int state[9], goal[9] = {1,2,3,4,5,6,7,8,0};
  8 int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; // 上,下,左, 右
  9 char path_dir[5] = "udlr";
 10 int st[MAXN][9];
 11 int father[MAXN], path[MAXN]; // 保存打印路径
 12
 13 const int MAXHASHSIZE = 1000003;
 14 int head[MAXHASHSIZE], next[MAXN];
 15
 16 void init_lookup_table() { memset(head, 0, sizeof(head)); }
 17
 18 typedef int State[9];
 19 int hash(State& s) {
 20   int v = 0;
 21   for(int i = 0; i < 9; i++) v = v * 10 + s[i];
 22   return v % MAXHASHSIZE;
 23
 24 }
 25
 26 int try_to_insert(int s) {
 27   int h = hash(st[s]);
 28   int u = head[h];
 29   while(u) {
 30     if(memcmp(st[u], st[s], sizeof(st[s])) == 0) return 0;
 31     u = next[u];
 32   }
 33   next[s] = head[h];
 34   head[h] = s;
 35   return 1;
 36 }
 37
 38 int bfs(){
 39     init_lookup_table();
 40     father[0] = path[0] = -1;
 41     int front=0, rear=1;
 42     memcpy(st[0], state, sizeof(state));
 43
 44     while(front < rear){
 45         int *s = st[front];
 46
 47         if(memcmp(s, goal, sizeof(goal))==0){
 48             return front;
 49         }
 50
 51         int j;
 52         for(j=0; j<9; ++j) if(!s[j])break; // 找出0的位置
 53         int x=j/3, y=j%3;     // 转换成行,列
 54
 55         for(int i=0; i<4; ++i){
 56
 57             int dx = x+dir[i][0]; // 新状态的行,列
 58             int dy = y+dir[i][1];
 59             int pos = dx*3+dy;    // 目标的位置
 60
 61             if(dx>=0 && dx<3 && dy>=0 && dy<3){
 62                 int *newState = st[rear];
 63                 memcpy(newState, s, sizeof(int)*9);
 64                 newState[j] = s[pos];
 65                 newState[pos] = 0;
 66                 if(try_to_insert(rear)){
 67                     father[rear] = front;  path[rear] = i;
 68                     rear++;
 69                 }
 70             }
 71         }
 72         front++;
 73     }
 74     return -1;
 75 }
 76
 77 void print_path(int cur){
 78     if(cur!=0){
 79         print_path(father[cur]);
 80         printf("%c", path_dir[path[cur]]);
 81     }
 82 }
 83
 84 int main(){
 85
 86     while(gets(input)){
 87         // 转换成状态数组, ‘x‘用0代替
 88         for(int pos=0, i=0; i<strlen(input); ++i){
 89             if(input[i]>=‘0‘ && input[i]<=‘9‘)
 90                 state[pos++] = input[i]-‘0‘;
 91             else if(input[i]==‘x‘)
 92                 state[pos++] = 0;
 93         }
 94         int ans;
 95         if((ans=bfs())!=-1){
 96             print_path(ans);
 97             printf("\n");
 98         }
 99     }
100 }

时间: 2024-08-07 17:02:11

八数码块的相关文章

八数码问题+路径寻找问题+bfs(隐式图的判重操作)

Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 process()  初始化vis数组,初始化初始节点到目标节点的移动距离 dfs()搜索到每一个节点,如果不是目标节点,对其依次扩展所有子节点,并判重,全部子节点搜索完全后,改变父节点:如果是目标节点成功返回 输出最少移动步数 input: 2 6 4 1 3 7 0 5 8 8 1 5 7 3 6

八数码

八数码问题 一.问题描述 所谓八数码问题是指:将分别标有数字1,2,3,…,8的八块正方形数码牌任意地放在一块3×3的数码盘上.放牌时要求不能重叠.于是,在3×3的数码盘上出现了一个空格.现在要求按照每次只能将与空格相邻的数码牌与空格交换的原则,将任意摆放的数码盘逐步摆成某种特殊的排列. 二.问题分析 首先,八数码问题包括一个初始状态(strat) 和 目标状态(goal),所谓解八数码问题就是在两个状态间寻找一系列可过渡状态(strat-> strat 1-> strat 2->...

【算法】BFS+哈希解决八数码问题

15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖"X"; 拼图的目的是安排瓷砖以便它们排序为: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15× 这里唯一合法经营是交流'X'与它共享一个边缘的瓷砖之一.作为一个例子,举动下列顺序解决了一个稍微加扰难题: 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6

HDU 1043 Eight(八数码)

p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-size: 10.5000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: center; font-family: 宋体; color: rgb(26,92,200); font-weight: bold; fo

1225 八数码难题

1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.问题描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765

HDU 1043 Eight八数码解题思路(bfs+hash 打表 IDA* 等)

题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原为初始状态 思路: 参加网站比赛时拿到此题目,因为之前写过八数码问题,心中暗喜,于是写出一套暴力bfs+hash,结果TLE呵呵 思路一:bfs+hash(TLE) 1 #include <cstdio> 2 #include <cstring> 3 #include <queu

洛谷【P1379】八数码难题

P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 输入输出格式 输入格式: 输入初试状态,一行九个数字,空格用0表示 输出格式: 只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊

八数码三种用时差距极大的写法

进化史,一种比一种长,一种比一种快.不过第三种似乎还不是最终形态. 第一种,傻逼级迭代加深. 去年十一月写的,那时候刚刚学迭代加深,敲了一个钟头才敲完,codevs上直接过,就没太管,觉得这是个水题.实际上呢,看后文. 1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 int sx,sy,lim,

八数码的八境界 [转载]

八数码的八境界   研究经典问题,空说不好,我们拿出一个实际的题目来演绎.八数码问题在北大在线测评系统中有一个对应的题,题目描述如下: Eight Time Limit: 1000MS    Memory Limit: 65536K  Special Judge Description The 15-puzzle has been aroundfor over 100 years; even if you don't know it by that name, you've seen it. I