八数码问题 - BFS

题目描述

八数码问题,即在一个3×3的矩阵中有8个数(1至8)和一个空格,现在要你从一个状态转换到另一个状态,每次只能移动与空格相邻的一个数字到空格当中,问题是要你求从初始状态移动到目标状态所需的最少步数。如下图所示。
八数码问题 - BFS_第1张图片
如上图所示的数据以矩阵形式给出。现在给出分别代表初始状态和目标状态的两个3*3的矩阵,请给出两个矩阵相互转化的最少步数。

输入

第1行-第3行:3个用空格分隔的整数,代表初始状态相应位置的数字,0代表空格
第4行-第6行:3个用空格分隔的整数,代表终止状态相应位置的数字,0代表空格

输出

第1行:一个整数,最小转换步数,如不能到相互转化则输出”Impossible”

样例输入

1 2 3
8 0 4
7 6 5
1 2 3
7 8 4
0 6 5

样例输出

2

题解

空间消耗最大的判重

#include 
#include 
#include 
#include 
#include 
using namespace std;

typedef int State[9];
const int MAXSTATE = 1000000;
State st[MAXSTATE],go;
const int dir[4][4]={{-1,0},{1,0},{0,-1},{0,1}};
int dist[MAXSTATE];
set<int> vis;
int try_to_insert(int s)//判重,若未出现则插入
{
    int v=0;
    for(int i=0;i<9;i++) v=v*10+st[s][i];
    if(vis.count(v)) return 0;//重复,返回0
    vis.insert(v);//不重复,插入并返回1
    return 1;
}
int BFS()
{
    vis.clear();
    int front=1,rear=2;
    while(front//用“引用”简化代码
        if(memcmp(go,s,sizeof(s))==0) return front;
        int z;
        for(z=0;z<9;z++) if(!s[z]) break;//找到'0'即空白位置
        int x=z/3,y=z%3;
        for(int d=0;d<4;d++){
            int newx=x+dir[d][0];
            int newy=y+dir[d][1];
            int newz=newx*3+newy;
            if(newx>=0&&newx<3&&newy>=0&&newy<3){
                State& t=st[rear];
                memcpy(&t,&s,sizeof(s));//拓展新状态
                t[newz]=s[z];
                t[z]=s[newz];
                dist[rear]=dist[front]+1;
                if(try_to_insert(rear))//判重
                    rear++;//队列+1
            }
        }
        front++;
    }
    return 0;
}
int main()
{
    int i;
    for(i=0;i<9;i++) scanf("%d",&st[1][i]);
    for(i=0;i<9;i++) scanf("%d",&go[i]);
    int ans=BFS();
    if(ans>0) printf("%d\n",dist[ans]);
    else printf("Impossible\n");
    return 0;
}

你可能感兴趣的:(C/C++,搜索)