博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Eight(经典题,八数码)
阅读量:7090 次
发布时间:2019-06-28

本文共 7064 字,大约阅读时间需要 23 分钟。

Eight

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 20993    Accepted Submission(s): 5634
Special Judge

Problem Description

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, several descriptions of configuration of the 8 puzzle. One 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. Do not print a blank line between cases.

 

 

Sample Input

2 3 4 1 5 x 7 6 8

 

 

Sample Output

ullddrurdllurdruldr

 

 

//就是类似九宫格那个游戏,不过这里9个格子大小都相等

//学了比较多的东西,才懂怎么做

这里我用的的是 A*+逆序数剪枝+hash判重 做的

A*其实也好理解,就是 bfs 升级版

这个博客写的很详细  

因为,无论怎么移动,逆序数的奇偶性是不变的,所以用这个能剪枝

最大的问题就是怎么判重了,最多不过 9!种情况么,362880 ,每种情况对应一个数字,用一个 vis[ ]就能判重了,然后hash 判重就好理解了

还有许多方法,推荐一篇博客  有兴趣可以看看

 

A* + hash 判重 + 曼哈顿距离

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 using namespace std; 11 12 const int maxn=4e5+10;// 400010 最多不超过这么多状态 362880 13 const int hash_[9]={ 1,1,2,6,24,120,720,5040,40320}; 14 struct Node 15 { 16 int state[3][3]; 17 int x,y; 18 int g,h; //g代表已耗费,h代表估计耗费 19 int hash_num; //这个状态的 hash 值 20 bool operator < (const Node PP) const 21 { 22 //return g+h > PP.g+PP.h; 23 //1638ms 24 return h==PP.h ? g>PP.g : h>PP.h; 25 //686ms 26 } 27 }star,ans; 28 29 int dx[4]={ 1,-1,0,0}; 30 int dy[4]={ 0,0,1,-1}; 31 char op_c[8]={ "durl"}; 32 struct Node2 33 { 34 int pre_hash; 35 char op; 36 }p[maxn]; 37 int vis[maxn]; 38 39 40 int count_hash(Node p)//获得hash值,计算的是 0-8 排列的hash 41 { 42 int i,j,k,hash_num=0; 43 for (i=0;i<9;i++) 44 { 45 k=0; 46 for (j=0;j
p.state[i/3][i%3]) 49 k++; 50 } 51 hash_num+=k*hash_[i]; 52 } 53 return hash_num; 54 } 55 56 int count_h(Node p)//注意位置,要细致 57 { 58 int i,all=0; 59 for (i=0;i<9;i++) 60 { 61 int e=p.state[i/3][i%3]; 62 if (e) 63 { 64 e-=1; 65 all+=abs(i/3-e/3)+abs(i%3-e%3); 66 } 67 } 68 return all; 69 } 70 71 72 void print(int h) 73 { 74 if (p[h].pre_hash==-1) return; 75 print(p[h].pre_hash); 76 printf("%c",p[h].op); 77 } 78 79 void A_star() 80 { 81 int i; 82 83 star.hash_num = count_hash(star); 84 star.g=0; 85 star.h=count_h(star); 86 87 memset(vis,0,sizeof(vis)); 88 vis[star.hash_num]=1; 89 p[star.hash_num].pre_hash=-1; //头节点 90 91 priority_queue
Q; 92 Q.push(star); 93 94 Node e,n; 95 int xx,yy; 96 97 if (star.hash_num==ans.hash_num)//这个不能丢 98 { 99 printf("\n");100 return;101 }102 while (!Q.empty())103 {104 e=Q.top();105 Q.pop();106 107 for (i=0;i<4;i++)108 {109 xx=e.x+dx[i];110 yy=e.y+dy[i];111 if (xx<0||yy<0||xx>=3||yy>=3) continue;112 113 n=e;114 n.x=xx;115 n.y=yy;116 swap(n.state[xx][yy],n.state[e.x][e.y]);117 n.g++;118 n.h=count_h(n);119 n.hash_num=count_hash(n);120 121 if (vis[n.hash_num]) continue;122 123 p[n.hash_num].pre_hash=e.hash_num; //记录这个状态的的父 hash124 p[n.hash_num].op=op_c[i]; //记录怎么由父hash移动来的125 126 vis[n.hash_num]=1;127 if (n.hash_num==ans.hash_num)//说明到了128 {129 print(n.hash_num);130 printf("\n");131 return;132 }133 Q.push(n);134 }135 }136 }137 138 int main()139 {140 char str[30];141 int i;142 143 for(i=0;i<9;i++) //终点144 ans.state[i/3][i%3]=(i+1)%9;145 ans.hash_num=count_hash(ans); //终点146 147 while(gets(str))148 {149 int i;150 int len=strlen(str);151 152 int j=0;153 for(i=0,j=0;i
temp[i]) k++;175 }176 if (k%2)177 printf("unsolvable\n");178 else179 A_star();180 }181 return 0;182 }183 184 /*//错在这,浪费我2小时,才找出来! == 竟然不报错,而且是全局变量,第一次也不会错!!!185 186 for (i=0,j=0;i
View Code

 

IDA* + 曼哈顿距离 这个空间就省下来了,改一下,十五数码也能做的,上一个就不行了,内存爆炸

1 #include 
2 #include
3 #include
4 #include
5 6 #define size 3 //这里规定几数码 7 8 int move[4][2]={
{-1,0},{
0,-1},{
0,1},{
1,0}};//上 左 右 下 置换顺序 9 char op[4]={
'u','l','r','d'}; 10 11 int map[size][size],map2[size*size],limit,path[100]; 12 int flag,length; 13 14 // 十五数码 的表 15 //int goal[16][2]= {
{size-1,size-1},{0,0},{0,1},{0,2}, 16 // {0,3},{1,0},{1,1},{1,2}, 17 // {1,3},{2,0},{2,1},{2,2}, 18 // {2,3},{3,0},{3,1},{3,2}};//各个数字应在位置对照表 19 20 // 八数码 的表 21 int goal[9][2]= {
{size-1,size-1},{
0,0},{
0,1},{
0,2}, 22 {
1,0},{
1,1},{
1,2}, 23 {
2,0},{
2,1}}; //各个数字应在位置对照表 24 25 int nixu(int a[size*size]) 26 { 27 int i,j,ni,w,x,y; //w代表0的位置 下标,x y 代表0的数组坐标 28 ni=0; 29 for(i=0;i
a[j]) 38 ni++; 39 } 40 } 41 //x=w/size; 42 //y=w%size; 43 //ni+=abs(x-(size-1))+abs(y-(size-1)); //最后加上0的偏移量 44 if(ni%2==0) 45 return 1; 46 else 47 return 0; 48 } 49 50 int hv(int a[][size])//估价函数,曼哈顿距离,小等于实际总步数 51 { 52 int i,j,cost=0; 53 for(i=0;i
0)//不和上一次移动方向相反,对第二步以后而言105 continue;106 nx=sx+move[i][0]; //移动的四步 上左右下107 ny=sy+move[i][1];108 109 if( 0<=nx && nx
View Code

 

转载于:https://www.cnblogs.com/haoabcd2010/p/5965050.html

你可能感兴趣的文章
Maven下载cxf所需要的jar包
查看>>
【转】Jmeter学习 笔记——测试计划元件
查看>>
xfce4 启用回收站
查看>>
JMeter性能测试入门篇,超详细
查看>>
Use custom widgets with Qt Designer: Promotion technique
查看>>
点滴积累【JS】---JS小功能(onmousedown实现鼠标拖拽div移动)
查看>>
BinaryReader 、BinaryWriter是方便用二进制方式读写int,double,string之类的数据
查看>>
(转)Linux下运行python
查看>>
【转】解决weblogic启动慢和创建域慢的方法
查看>>
信息安全基础第一周作业
查看>>
GET和POST区别
查看>>
MySql 数据库系列问题
查看>>
BFC是什么?有什么作用?
查看>>
010.简单查询、分组统计查询、多表连接查询(sql实例)
查看>>
3_Windows下利用批处理文件_去除C源代码中指示行号的前导数字
查看>>
Bzoj 1853: [Scoi2010]幸运数字 容斥原理,深搜
查看>>
Hdu 4311-Meeting point-1 曼哈顿距离,前缀和
查看>>
docker网络介绍之bridge网络详解
查看>>
两个PHP方面的东西,超过2038的时间和唯一订单号算法
查看>>
凡事预则立
查看>>