Partychen invents a new game named “Eleven Puzzle” .Just like the classic game “Eight Puzzle”,but there some difference between them:The shape of the board is different and there are two empty tiles. 

The tile in black means it’s empty

Each step you can move only one tile. 
Here comes the problem.How many steps at least it required to done the game. 

 

Input

The first line of input contains one integer specifying the number of test cases to follow. 
Every case contains five lines to describe the initial status of the board. 0 means empty.

It’s confirmed that the board is legal.

 

Output

Output one line for each testcase.Contain an integer denotes the minimum step(s) it need to complete the game.Or “No solution!” if it’s impossible to complete the game within 20 steps.
 

Sample Input

3
2
1 0 3
4 5 6 7 8
9 0 11
10
0
1 2 3
4 5 6 7 8
9 10 11
0
0
11 10 9
8 7 6 5 4
3 2 1
0
 

Sample Output

2
0
No solution!
 
题意:给出上图的11数码,有2个空格,每次可以移一步,问能否在20步以内达到目标状态,如果能输出步数,否则输出No solution!
 
解析:题目给了20步的限制,而且前后搜效果是一样的,所以很容易想到双向bfs,但是状态怎么保存呢,有11个数外加2个空格,可以考虑用康拓展开,但不能用数组保存值,因为值太大了,所以可以考虑用map,我用的方法是哈希,给每个数乘上一个权值,然后加起来哈希成一个值,用数组模拟链表保存状态,但可能出现两种不同的状态哈希成同一个值,所以在相同的情况下还要整个进行对比。
 
源代码
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<utility>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<iterator>
#include<stack>
using namespace std;
const int INF=1e9+;
const double eps=1e-;
const int mod=;
const int maxn=;
int f[],r[]; //双向bfs的两个队列的队首队尾指针
int dx[]={-,,,},dy[]={,-,,}; //方向数组
bool in(int x,int y){ return x>=&&x<&&y>=&&y<; } //是否越界
struct node
{
int px[],py[]; //保存2个空格的位置和整个数组
int A[][];
}nod[][maxn]; //0是前面搜,1是后面搜
int B[][]={ //最终状态
-,-,,-,-,
-,,,,-,
,,,,,
-,,,,-,
-,-,,-,-
};
bool Same(int A[][]) //判断该状态是否与最终的状态相等
{
for(int i=;i<;i++)
for(int j=;j<;j++)
if(A[i][j]!=B[i][j]) return false;
return true;
}
int F[]; //保存2^i
void GetF()
{
F[]=;
for(int i=;i<;i++) F[i]=F[i-]*;
}
int Get(int A[][]) //得到哈希值
{
int ret=,k=;
for(int i=;i<;i++)
for(int j=;j<;j++) if(A[i][j]>) ret+=F[k++]*A[i][j]; //乘上一个权值
return ret;
}
struct Hash
{
int v,next,nid,k; //是哈希值,next指向下一个节点,nid和k分别保存是下标和0或1
}ha[mod+maxn];
int hash_id;
bool check(int a,int k1,int b,int k2) //判断是否完全相等
{
for(int i=;i<;i++)
for(int j=;j<;j++)
if(nod[k1][a].A[i][j]!=nod[k2][b].A[i][j]) return false;
return true;
}
int Insert_Hash(int v,int nid,int k) //插入
{
int a=v%mod;
int p=ha[a].next;
while(p!=-)
{
if(ha[p].v==v&&check(ha[p].nid,ha[p].k,nid,k)) return ha[p].k;//有相同的状态
p=ha[p].next;
}
p=++hash_id; //没有则增加新节点,前插法
ha[p].v=v; ha[p].nid=nid; ha[p].k=k;
ha[p].next=ha[a].next; ha[a].next=p;
return -; //-1代表插入了新节点
}
bool AddNode(node& t,int i,int j,int k)
{
int x=t.px[i],y=t.py[i];
int nx=x+dx[j],ny=y+dy[j];
if(!in(nx,ny)||t.A[nx][ny]<=) return false;
node& tt=nod[k][r[k]];
tt=t;
swap(tt.A[x][y],tt.A[nx][ny]); //交换
tt.px[i]=nx; tt.py[i]=ny;
int a=Insert_Hash(Get(tt.A),r[k],k);
if(a==-){ r[k]++; return false; } //队尾指加1
else if(a==k) return false; //自己原来访问过的状态
else return true; //相遇了,找到了解
}
void Print(node& t)
{
for(int i=;i<;i++)
{
for(int j=;j<;j++) printf("%d ",t.A[i][j]);
puts("");
}
puts("=========");
getchar();
}
bool bfs(int k)
{
int& be=f[k];
int en=r[k];
while(be<en)
{
node& t=nod[k][be++];
//Print(t);
for(int i=;i<;i++)
for(int j=;j<;j++) if(AddNode(t,i,j,k)) return true;
}
return false;
}
int solve()
{
if(Same(nod[][].A)) return ;
for(int i=;i<;i++)
for(int j=;j<;j++) nod[][].A[i][j]=B[i][j]; //最终状态
nod[][].px[]=; nod[][].py[]=;
nod[][].px[]=; nod[][].py[]=;
int step=;
f[]=f[]=,r[]=r[]=;
for(int i=;i<mod;i++) ha[i].next=-;
hash_id=mod-;
while(f[]<r[]||f[]<r[]) //双向搜
{
step++;
if(bfs()) return step;
step++;
if(bfs()) return step;
if(step>=) return -;
}
return -;
}
int main()
{
int T;
GetF();
scanf("%d",&T);
while(T--)
{
int k=;
for(int i=;i<;i++)
for(int j=;j<;j++)//得到初始状态
{
if(B[i][j]==-) { nod[][].A[i][j]=-; continue; }
scanf("%d",&nod[][].A[i][j]);
if(nod[][].A[i][j]==)
{ nod[][].px[k]=i; nod[][].py[k++]=j; }
}
int ans=solve();
if(ans==-) printf("No solution!\n");
else printf("%d\n",ans);
}
return ;
}

hdu3095-Eleven puzzle(双向搜索+哈希)的更多相关文章

  1. Eleven puzzle_hdu_3095(双向广搜).java

    Eleven puzzle Time Limit: 20000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  2. Eight(bfs+全排列的哈希函数)

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22207   Accepted: 9846   Special Judge ...

  3. poj1200Crazy Search (哈希)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Crazy Search Time Limit: 1000MS   Memory ...

  4. POJ 1200:Crazy Search(哈希)

    Crazy Search Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32483   Accepted: 8947 Des ...

  5. POJ-3131-Cubic Eight-Puzzle(双向BFS+哈希)

    Description Let's play a puzzle using eight cubes placed on a 3 × 3 board leaving one empty square. ...

  6. Crazy Search POJ - 1200 (字符串哈希hash)

    Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could ...

  7. [PHP内核探索]PHP中的哈希表

    在PHP内核中,其中一个很重要的数据结构就是HashTable.我们常用的数组,在内核中就是用HashTable来实现.那么,PHP的HashTable是怎么实现的呢?最近在看HashTable的数据 ...

  8. java单向加密算法小结(2)--MD5哈希算法

    上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...

  9. Java 哈希表运用-LeetCode 1 Two Sum

    Given an array of integers, find two numbers such that they add up to a specific target number. The ...

随机推荐

  1. Oracle百问百答(四)

    Oracle百问百答(四) 31.怎样查看某用户下的表? select table_name from all_tables where owner=upper('jhemr'); 32.怎样查看某用 ...

  2. 看了一本书,说可以利用Hierarchy Viewer优化布局

    看了一本书,说可以利用Hierarchy Viewer优化布局,今以志之. 参考:http://www.cnblogs.com/Rocky_/archive/2011/11/04/2236243.ht ...

  3. (转)A drop-in universal solution for moving text fields out of the way of the keyboard

    There are a hundred and one proposed solutions out there for how to move UITextField andUITextView o ...

  4. laravel-模板引擎Blade

    (慕课网_轻松学会Laravel-基础篇_天秤vs永恒老师) 一.概述 Blade是Laravel提供的一个既简单又强大的模板引擎 和其他流行的PHP模板引擎不一样,Blade并不限制你在视图view ...

  5. WebView使用

    WebView是View的一个子类,可以让你在activity中显示网页. 可以在布局文件中写入WebView:比如下面这个写了一个填满整个屏幕的WebView: <?xml version=& ...

  6. Understanding Abstractions of Secure Channels 的研读

  7. Linux下找不到动态链接库

    1.生成静态库 生成静态库使用ar工具,其实ar是archive的意思 $ar cqs libhello.a hello.o 2.生成动态库 用gcc来完成,由于可能存在多个版本,因此通常指定版本号: ...

  8. p标签里面不要放div标签(块元素)

    最好不要在p标签里面嵌套块级元素(如div Ul): <p>我来测试下<div>块元素</div>放在p标签的情况</p> <p>我来测试下 ...

  9. CentOS管理

    1.使用yum安装和卸载软件 主要功能是更方便的添加/删除/更新RPM包. 它能自动解决包的倚赖性问题. 它能便于管理大量系统的更新问题 一.yum list|more               列 ...

  10. Sass函数--map

    MapSass 的 map 常常被称为数据地图,也有人称其为数组,是以 key:value 成对的出现. $map: ( $key1: value1, $key2: value2, $key3: va ...