码迷,mamicode.com
首页 > 其他好文 > 详细

Eight(经典题,八数码)

时间:2016-10-15 19:58:07      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:

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 升级版

这个博客写的很详细  http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx

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

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

还有许多方法,推荐一篇博客 http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 有兴趣可以看看

 

技术分享
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <iostream>
  7 #include <queue>
  8 #include <map>
  9 #include <vector>
 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<i;j++)
 47         {
 48             if (p.state[j/3][j%3]>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 <Node> 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;  //记录这个状态的的父 hash
124             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<len;i++)
154         {
155             if(str[i]== )continue;
156             if(str[i]==x)
157             {
158                 star.state[j/3][j%3]=0;
159                 star.x=j/3;
160                 star.y=j%3;
161             }
162             else star.state[j/3][j%3]=str[i]-0;
163             j++;                         // j/3 记录行数
164         }
165 
166         //判断逆序数
167         int temp [9],k=0;
168         for (i=0;i<9;i++)
169             temp[i]=star.state[i/3][i%3];
170         for (i=0;i<9;i++)
171         {
172             if (temp[i]==0) continue;
173             for (int j=0;j<i;j++)
174                 if (temp[j]>temp[i]) k++;
175         }
176         if (k%2)
177             printf("unsolvable\n");
178         else
179             A_star();
180     }
181     return 0;
182 }
183 
184 /*//错在这,浪费我2小时,才找出来! == 竟然不报错,而且是全局变量,第一次也不会错!!!
185 
186         for (i=0,j=0;i<len;i++)
187         {
188             if (str[i]==‘ ‘)continue;
189             else if (str[i]==‘x‘)
190             {
191                 star.x=j/3;
192                 star.y=j%3;
193                 star.state[j/3][j%3]==0;
194             }
195             else star.state[j/3][j%3]=str[i]-‘0‘;
196             j++;
197         }
198 */
View Code

 

Eight(经典题,八数码)

标签:

原文地址:http://www.cnblogs.com/haoabcd2010/p/5965050.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!