hihocoder#1312 : 搜索三·启发式搜索(bfs+hash判重)

来源:互联网 发布:redis安装 windows 编辑:程序博客网 时间:2024/06/03 20:37

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

在小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!"

样例输入
31 2 34 5 67 8 01 2 34 5 68 7 08 0 15 7 43 6 2
样例输出
0No Solution!25
思路:bfs。9个格子形成一个9位数,用hash链表判重。

#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;}