zoukankan      html  css  js  c++  java
  • 八数码

    八数码问题

    一、问题描述

    所谓八数码问题是指:将分别标有数字1,2,3,…,8的八块正方形数码牌任意地放在一块3×3的数码盘上。放牌时要求不能重叠。于是,在3×3的数码盘上出现了一个空格。现在要求按照每次只能将与空格相邻的数码牌与空格交换的原则,将任意摆放的数码盘逐步摆成某种特殊的排列。

    二、问题分析

    首先,八数码问题包括一个初始状态(strat) 和 目标状态(goal),所谓解八数码问题就是在两个状态间寻找一系列可过渡状态(strat-> strat 1-> strat 2->...->goal)。这个状态是否存在就是我们要解决的第一个问题。如下是初使状态到目标状态图:(0表示空格)

    1

    2

    3

    7

    4

    5

    8

    0

    6

    1

    2

    3

    4

    5

    6

    7

    8

    0

     
       

    三、数据结构

    定义结构体Node如下:

    typedef struct{

        int num[9];                

        char cur_expension;         //记录是否可以扩展,Y代表可以扩展,N代表不可以

        char Operate;       //表示不可以执行的操作,L代表不能左移,R代表不能右移,

                        //U代表不能上移,D代表不能下移,C代表可以任意移动。

        int father;                     //记录父节点的下标。

    }Node;

    Node state[MAXSIZE];

    四、广度优先搜索

    广度优先搜索是指按节点的层次进行搜索,本层的节点没有搜索完毕时,不能对下层节点进行处理,即深度越小的节点越先得到扩展,也就是说先产生的节点先得以扩展处理,直至找到目标为止。求解八数码问题的搜索过程:如图2所示,把所有可能的算符应用到开始节点(即空格上移、空格左移、空格右移、空格下移),图2只是演示了两个扩展结点,如此继续下去,直到发现目标节点。

     
       

     

                                                            

        

                                              

    变量定义及函数说明:

    #define SUM 100        //限定只搜索前100步,100步以后如果仍然没有搜索到结果,认为无解。

    #define MAXSIZE 200  //定义最大数组长度

    int n=1;                      //用来记录搜索的步骤

    int goal[9]={1,2,3,7,4,5,8,0,6};//所要达到的最终状态,0代表空格

    int same(int temp); //判断是否达到了目标状态

    void printgoal();       //输出搜索结果

    int left(int temp); //将空格进行左移操作

    int right(int temp);    //将空格进行右移操作

    int up(int temp);       //将空格进行上移操作

    int down(int temp); //将空格进行下移操作

    void init();           //初始状态参数设置

    五、  程序运行结果

    从初始状态到目标状态走了42步

     

     

    六、源程序如下

    #include <iostream>

    #include <stdlib.h>

    using namespace std;

    int same(int temp); //判断是否达到了目标状态

    void printgoal();       //输出搜索结果

    int left(int temp); //将空格进行左移操作

    int right(int temp);    //将空格进行右移操作

    int up(int temp);       //将空格进行上移操作

    int down(int temp); //将空格进行下移操作

    void init();           //初始状态参数设置      

    #define SUM 100        //限定只搜索前100步,100步以后如果仍然没有搜索到结果,认为无解

    #define MAXSIZE 200    

    int n=1;               

    int goal[9]={1,2,3,7,4,5,8,0,6};//所要达到的最终状态,0代表空格

     

    typedef struct{

        int num[9];                

        char cur_expension;         //记录是否可以扩展,Y代表可以扩展,N代表不可以

        char Operate;       //表示不可以执行的操作,L代表不能左移,R代表不能右移,

                        //U代表不能上移,D代表不能下移,C代表可以任意移动。

        int father;                     //记录父节点的下标。

    }Node;

    Node state[MAXSIZE];                //将搜索过的状态存储于该数组中。

     

    int main()

    {

        init();

        if(same(0))

        {

            cout<<"没有必要进行搜索,初始状态即为最终状态!"<<endl;

            while (true);

        }

        for(int i=0;i<SUM;i++)          //开始进行广度搜索,限定搜索上限为100步。

        {

        if(state[i].cur_expension=='Y')

        {

            if(state[i].Operate=='L')

            {      

                up(i);

                right(i);

                down(i);

            }

            if(state[i].Operate=='R')

            {

                left(i);

                up(i);

                down(i);

            }

            if(state[i].Operate=='U')

            {

                left(i);

                right(i);

                down(i);

            }

            if(state[i].Operate=='D')

            {

                left(i);

                up(i);

                right(i);

            }

            if(state[i].Operate=='C')

            {

                left(i);           

                up(i);

                right(i);

                down(i);

            }

        }

        if(n>=SUM)                  //100步以后仍然没有达到所要求的状态,认为无解。

        {

            n--;

            printgoal();

            cout<<"对不起,在所在搜索范围内没有搜索到结果!"<<endl;

            while (true);

        }

        }

        while(1);

     return 0; 

    }

    int same(int temp)                  //判断是否达到了目标状态。

    {

        for(int j=0;j<9;j++)

            if(state[temp].num[j]!=goal[j])

                return 0;

        return 1;

    }

    void printgoal()                    //输出搜索结果。

    {

        for(int j=1;j<=n;j++)

        {

            cout<<"第"<<j<<"步搜索后:"<<endl;

            cout<<state[j].num[0]<<" "<<state[j].num[1]<<" "<<state[j].num[2]<<endl;

            cout<<state[j].num[3]<<" "<<state[j].num[4]<<" "<<state[j].num[5]<<endl;

            cout<<state[j].num[6]<<" "<<state[j].num[7]<<" "<<state[j].num[8]<<endl;

            cout<<endl;

        }

        cout<<"成功搜索得到结果!"<<endl;

    }

    int left(int temp)                      //将空格进行左移操作。

    {

        int j;

        for(j=0;j<9;j++)                //判断空格的位置。

            if(state[temp].num[j]==0)

                break;

        if(j==0||j==3||j==6)

            return 0;

        for(int k=0;k<9;k++)

            state[n].num[k]=state[temp].num[k];

        int tempNum=state[n].num[j-1];      //将移动后的状态赋给state[n]

        state[n].num[j-1]=0;

        state[n].num[j]=tempNum;

        state[temp].cur_expension='N';

        state[n].Operate='R';

        state[n].cur_expension='Y';

        state[n].father=temp;

        if(same(n))                         //判断state[n]是否为最终想得到的状态。

        {

            printgoal();

            while (true);

        }

        n++;

        return 1;

    }

    int right(int temp)                     //将空格进行右移操作。

    {

        int j=0;

        for(;j<9;j++)

            if(state[temp].num[j]==0)

                break;

        if(j==2||j==5||j==8)

            return 0;

        for(int k=0;k<9;k++)

            state[n].num[k]=state[temp].num[k];

        int tempNum=state[n].num[j+1];

        state[n].num[j+1]=0;

        state[n].num[j]=tempNum;

        state[temp].cur_expension='N';

        state[n].Operate='L';

        state[n].cur_expension='Y';

        state[n].father=temp;

        if(same(n))

        {

            printgoal();

            while (true);

        }

        n++;

        return 1;

    }

    int up(int temp)                        //将空格进行上移操作。

    {

        int j=0;

        for(;j<9;j++)

            if(state[temp].num[j]==0)

                break;

        if(j==0||j==1||j==2)

            return 0;

        for(int k=0;k<9;k++)

            state[n].num[k]=state[temp].num[k];

        int tempNum=state[n].num[j-3];

        state[n].num[j-3]=0;

        state[n].num[j]=tempNum;

        state[temp].cur_expension='N';

        state[n].Operate='D';

        state[n].cur_expension='Y';

        state[n].father=temp;

        if(same(n))

        {

            printgoal();

            while (true);

        }

        n++;

        return 1;

    }

    int down(int temp)                      //将空格进行下移操作。

    {

        int j=0;

        for(;j<9;j++)

            if(state[temp].num[j]==0)

                break;

        if(j==6||j==7||j==8)

            return 0;

        for(int k=0;k<9;k++)

            state[n].num[k]=state[temp].num[k];

        int tempNum=state[n].num[j+3];

        state[n].num[j+3]=0;

        state[n].num[j]=tempNum;

        state[temp].cur_expension='N';

        state[n].Operate='U';

        state[n].cur_expension='Y';

        state[n].father=temp;

        if(same(n))

        {

            printgoal();

            while (true);

        }

        n++;

        return 1;

    }

    void init()                            

    {

        Node start;

       cout<<"初始状态为:(0代表空格)"<<endl;//初始的状态的生成。

       for(int i=0;i<9;i++)

       {

           start.num[i]=(i+1)%9;

           cout<<start.num[i]<<" ";

           if((i+1)%3==0)

               cout << endl;

        }

       cout<<endl;

       cout<<"目标状态为:"<<endl;

      for(int i=0;i<9;i++){

          cout<<goal[i]<<" ";

           if((i+1)%3==0)

               cout << endl;

      }

        cout<<endl;

        for(int k=0;k<9;k++)

            if(start.num[k]==0)

                break;

            start.Operate='C';

        start.cur_expension='Y';

        start.father=-1;

        state[0]=start;                                 //将初始状态赋于state[0]。

    }

  • 相关阅读:
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第5节 String类_7_字符串的转换相关方法
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第5节 String类_6_字符串的截取方法
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第5节 String类_5_字符串的获取相关方法
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第5节 String类_2_字符串的构造方法和直接创建
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第4节 ArrayList集合_19-ArrayList练习四_筛选集合
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第5节 String类_1_字符串概述和特点
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第4节 ArrayList集合_18-练习三_按指定格式打印集合的方法
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第4节 ArrayList集合_17-ArrayList练习二_存储自定义
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第4节 ArrayList集合_16-ArrayList练习一_存储随机数
    阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第4节 ArrayList集合_15-ArrayList集合存储基本数据
  • 原文地址:https://www.cnblogs.com/mymint/p/4593778.html
Copyright © 2011-2022 走看看