八数码问题

                                                                                                八数码问题

题意:

         编号为1~8的8个正方形滑块被摆成3行3列(有一个格子留空),如下图所示       每次可以把与空格相邻的滑块(有公共边才算相邻)移到空格中,而他原来的位置   就成为了新的空格。如果无法到达目标局面,则输出-1 。

      2         6        4    
    1       3    7
         5     8

移到后
          8                 1                5     
          7             3           6
          4             2 

样例输入:

2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

样例输出:

31

【分析】

           八数码很像我们小时候玩的拼图游戏,就是把打乱的图拼成指定形状。可以

    把题看成求最短路径问题,只是在原来的基础上增加了不少难度,增加了每的

    判断0的位置,和0的移动,还要保存每步后的移动结果,判断重复。数组不要开

    大因为数据移动最大可达到9!个(9!=362 880),还要定义长度为9的数组,

    要来保存移动时的数据情况。

【代码】

#include
#include
#include
using namespace std;
typedef int State[9];       // 储存表格
const int maxstate = 1000000;   // 最大1000000步
State st[maxstate],goal;        // 定义goal[9],定义st[maxstate][9]
int dist[maxstate];     // 存储步数

const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
setvis;
void init_lookup_table()
{
    vis.clear();
}
int try_to_insert(int s)
{
    int v=0;
    for(int i=0;i<9;i++)
        v=v*10+st[s][i];    // 将现在的阵列生成一个9位数
    if(vis.count(v))        // 查找是否用过
        return 0;
    vis.insert(v);          // 插入set容器,用于标记
    return 1;
}
// 广搜
int bfs()
{
    init_lookup_table();
    int front=1,rear=2;
    while(front=0&&newx<3&&newy>=0&&newy<3)    // 判断是否越界
            {
                State& t=st[rear];          // 定义t[9]
                memcpy(&t,&s,sizeof(s));    // 将s的数据赋给t
                // 0的移动,两位置互换
                t[newz]=s[z];   // 移动0到(newx,newy)处
                t[z]=s[newz];   // (newx,newy)的数据移动原来0的位置
               // printf("t[newz]=%d  t[z]=%d,z=%d\n",t[newz],t[z],z);
                dist[rear]=dist[front]+1;   // 储存步数
                if(try_to_insert(rear))
                    rear++;                 // 尾指针后移
            }
        }
        front++;
    }
    return 0;
}

int main()
{
    for(int i=0;i<9;i++)
        scanf("%d",&st[1][i]);
    for(int i=0;i<9;i++)
        scanf("%d",&goal[i]);
    int ans=bfs();  // 返回头地址
    if(ans>0)
        printf("%d\n",dist[ans]);  // 输出存储的步数
    else printf("-1\n");        // 如果找不到输出-1
    return 0;
}
代码注释有不当之处或有更好的代码,麻烦大神留言!

你可能感兴趣的:(搜索)