时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
3 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 8 7 0 8 0 1 5 7 4 3 6 2
样例输出
-
0 No Solution! 25
描述
在小Ho的手机上有一款叫做八数码的游戏,小Ho在坐车或者等人的时候经常使用这个游戏来打发时间。
游戏的棋盘被分割成3x3的区域,上面放着标记有1~8八个数字的方形棋子,剩下一个区域为空。
游戏过程中,小Ho只能移动棋子到相邻的空区域上。当小Ho将8个棋子都移动到如下图所示的位置时,游戏就结束了。
小Hi:小Ho,你觉得如果用计算机来玩这个游戏应该怎么做?
小Ho:用计算机来玩么?我觉得应该是搜索吧,让我想一想。
输入
第1行:1个正整数t,表示数据组数。1≤t≤8。
接下来有t组数据,每组数据有3行,每行3个整数,包含0~8,每个数字只出现一次,其中0表示空位。
输出
第1..t行:每行1个整数,表示该组数据解的步数。若无解输出"No Solution!"
#include<bits/stdc++.h>
using namespace std;
const int hashsize=1000007;
int head[hashsize],nex[hashsize],Hash[hashsize],Size;//hash链表
int a[20];//记录状态
struct lenka//记录状态和步数
{
int sum,step;
};
int n()//把当前状态变为一个9位数
{
int sum=0;
for(int i=1;i<=9;i++)sum=sum*10+a[i];
return sum;
}
int Insert()//插入
{
int tp=n();
for(int i=head[tp%hashsize];i!=-1;i=nex[i])if(Hash[i]==tp)return 0;//插入失败
nex[Size]=head[tp%hashsize];
head[tp%hashsize]=Size;
Hash[Size]=tp;
Size++;
return 1;
}
void bfs()
{
Insert();
queue<lenka>p;
p.push((lenka){n(),0});
while(!p.empty())
{
lenka now=p.front();p.pop();
if(now.sum==123456780){printf("%d\n",now.step);return;}//找到答案
for(int i=9;i>=1;i--,now.sum/=10)a[i]=now.sum%10;
for(int i=0;i<3;i++)
{
for(int j=1;j<=3;j++)
{
if(a[i*3+j])continue;
if(i)//0与上面那个数交换位置
{
swap(a[i*3+j],a[(i-1)*3+j]);
if(Insert())p.push((lenka){n(),now.step+1});
swap(a[i*3+j],a[(i-1)*3+j]);
}
if(i<2)//0与下面那个数交换位置
{
swap(a[i*3+j],a[(i+1)*3+j]);
if(Insert())p.push((lenka){n(),now.step+1});
swap(a[i*3+j],a[(i+1)*3+j]);
}
if(j>1)//0与左边那个数交换位置
{
swap(a[i*3+j],a[i*3+j-1]);
if(Insert())p.push((lenka){n(),now.step+1});
swap(a[i*3+j],a[i*3+j-1]);
}
if(j<3)//0与右边那个数交换位置
{
swap(a[i*3+j],a[i*3+j+1]);
if(Insert())p.push((lenka){n(),now.step+1});
swap(a[i*3+j],a[i*3+j+1]);
}
}
}
}
puts("No Solution!");
}
int main()
{
int T;cin>>T;
while(T--)
{
for(int i=1;i<=9;i++)scanf("%d",&a[i]);
memset(head,-1,sizeof head);
memset(nex,-1,sizeof nex);
Size=0;
bfs();
}
return 0;
}