本题有写法好几个写法,但主要思路是BFS:
No。1
采用双向宽搜,分别从起始态和结束态进行宽搜,暴力判重。如果只进行单向会超时。
No。2
采用hash进行判重,宽搜采用单向就可以AC。
No。3
运用康拓展开进行判重,即使采用单向宽搜时间效率也很高。
哈希是想到了,但是我们应该选择什么哈希函数呢,看了网上一些神牛利用的是"康托展开",也就是利用全排列都有一个对应的整数,利用哈希函数把状态压缩成整数,这样就可以做到每一个整数都是唯一对应一个状态,那么这个时候就把哈希做完了。
Eight
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 29838 Accepted Submission(s): 7831
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
Source
South Central USA 1998 (Sepcial Judge Module By JGShining)
【代码】:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//思路: 单向bfs()+哈希判重+路径输出(由于POJ数据只有一组,这个方法可以在POJ上面A,其它oj不能A )
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXN 400000
struct State{
int state[9];
int pos;//空格位置
char ch[50];//记录原始状态到达当前状态的路径(数组不能开太大不然超内存)
}s[MAXN];//每一个状态对应一个结构体
int factor[9] = {1,1,2,6,24,120,720,5040,40320};//阶乘数组
int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};//方向数组
char dirtion[4] = {'u' , 'r' , 'd' , 'l'};
int vis[MAXN];//标记某个状态是否被走过
int start;//保存原始输入状态的哈希值
State star;//原始状态对应的结构体
queueq;//这里不能直接放结构体,不然肯定超时
//哈希映射
int Hash(int s[]){
int i , j , temp , num;
num = 0 ;
for(i = 0 ; i < 9 ; i++){
temp = 0;
for(j = i+1 ; j < 9 ; j++){
if(s[j] < s[i]) temp++;
}
num += factor[8-i]*temp;
}
return num;
}
//广搜
bool Bfs(){
while(!q.empty()) q.pop();
memset(vis , 0 , sizeof(vis));
start = Hash(star.state);
vis[start] = 1;
s[start] = star;
q.push(start);
while(!q.empty()){
State cur = s[q.front()];
q.pop();
int x , y , r , c;
x = cur.pos/3 ; y = cur.pos%3;
for(int i = 0 ; i < 4 ; i++){
r = x+dir[i][0] ; c = y+dir[i][1];
if(r < 0 || c < 0 || r >= 3 || c >= 3) continue;
State tmp = cur;
tmp.state[tmp.pos] = tmp.state[3*r+c];//原先空格位置换成新的编号
tmp.pos = 3*r+c ; tmp.state[tmp.pos] = 9;//重新更新空格位置
int hash = Hash(tmp.state);//求出当前哈希值
if(vis[hash]) continue;
vis[hash] = 1;
int len = strlen(cur.ch);//求出前一个状态的路径长度
tmp.ch[len] = dirtion[i];//更新路径
s[hash] = tmp;//赋值
if(hash == 0){//如果搜索到目标节点直接输出退出
printf("%s\n" , s[hash].ch) ; return 1;
}
q.push(hash);//入对列
}
}
return 0;
}
int main(){
char c;
while(scanf("%c" , &c) != EOF){
if(c == 'x'){ star.state[0] = 9 ; star.pos = 0;}
else star.state[0] = c-'0';
for(int i = 1 ; i < 9 ; i++){
scanf(" %c" , &c);
if(c == 'x'){ star.pos = i ; star.state[i] = 9;}
else star.state[i] = c-'0';
}
getchar();
int flag = Bfs();
if(!flag) printf("unsolvable\n");//无解的情况
}
return 0;
}