BFS解决八数码问题

0x01数据结构介绍:

用grid类实现棋盘

包括:

1、一维数组存储棋盘状态

2、my_index、parent存储自己下标和父节点下标

3、string str_state 实现用字符串表达棋盘状态

class grid{
public:
    int state[9];     //one_dimensional_vector    
    int my_index;
    int parent;   
    string str_state;
    string movement;     //进行到本状态'0'需执行的动作
    //构造函数
    grid(int state[9], int parent, string movement)
    {
        for(int i = 0; i < 9; i ++)
                 this->state[i] = state[i];

        this->parent = parent;
        this->movement = movement;
    }       
    grid() {}
    void create_newstate(int dir);
    void Numarry_to_String();
    bool isend();
};

每生成一个棋盘状态,便将其push到vector(grid)中去,实现父子节点关系的表示

map<string, int> HashMap

其中key为期盼状态,value为棋盘下标,每次生成新的棋盘状态,便在HashMap中查找有无该状态:

若有,则不生成

若没有,则生成。

stack<grid>

查找到后,用该stack存储父节点。

0x02算法介绍:

生成新结点:

对读取到的节点进行上下左右四个方向生成新结点。

对于每一个给定方向(dir),判断一下能否向该方向移动:

若能,则两个点交换位置,并返回true

若不能,直接返回false
bool getNewGrid(grid &nownode,int dir)
{
    int index;
    for(int i = 0; i < 9; i ++)
              if(nownode.state[i] == 0)
                    index = i;
    switch (dir)          
    {
    case -3:  //index向上 i>=3
       if(index >= 3)
          swap(nownode.state[index],nownode.state[index-3]);   
          nownode.Numarry_to_String();
          return true;              
       break;  
    case 3: 
       if(index <= 5) //index向下 i <= 5
           swap(nownode.state[index],nownode.state[index+3]);
           nownode.Numarry_to_String();
           return true;
        break;
    case 1:       //index 向右 i!=2,5,8;
       if(index!=2 && index != 5 && index !=8 )
           swap(nownode.state[index],nownode.state[index+1]);
           nownode.Numarry_to_String();
           return true;
        break;
    case -1: 
        if(index%3 != 0)  //index向左
           swap(nownode.state[index],nownode.state[index-1]);
           nownode.Numarry_to_String();
           return true;
        break;
    default:
        return false;
        break;
    }
}

BFS

用队列存储生成的新节点。每次从队列首部开始访问,并出队列,实现宽度搜索

若搜到,则进行回推:

上述的栈此时起到了作用,先一路回溯,每遇到一个父节点就将其入栈,一直到initial节点为止。

再从栈顶开始出栈并输出,实现了每一步打印的效果。

若当前节点不是目标节点,则更新parent_index以及my_index并将该节点入vector(其中my_index就是该节点vector下标,parent_index就是父节点在vector中的下标)并将该节点入队列待搜索。

if(NewGrid.isend())
                {
                   stack<grid> path;
                   grid ParentGrid = NewGrid;
                   path.push(ParentGrid);
                   while(ParentGrid.parent != -1)
                   {
                      path.push(GList[ParentGrid.parent]);
                      ParentGrid = GList[ParentGrid.parent];
                   } 
                   //path.push(ParentGrid);
                   int step = 0;
                   while(!path.empty())
                   {
                       grid prinGrid = path.top();
                       path.pop();
                       if(step == 0) cout<<prinGrid.movement<<endl;
                       else 
                            cout<<"step "<<step<<endl;
                       for(int i = 0; i < 9 ; i ++)
                       {    
                           cout<<prinGrid.state[i]<<" ";
                           if(i == 2|| i ==5 || i == 8)
                           cout<<endl;   
                       }
                       step++;
                    }
                    return true;
                }
if(HashMap.find(NewGrid.str_state) == HashMap.end()) //不存在
                {
                    HashMap.insert(pair(NewGrid.str_state,MapIndex));
                    MapIndex ++;
                    GridQueue.push(NewGrid);
                }

完整代码

#include 
#include 
#include     //key: string
#include 
#include 
#include 
using namespace std;

//哈希存储状态

class grid{
public:
    int state[9];     //one_dimensional_vector    
    int my_index;
    int parent;   
    string str_state;
    string movement;     //进行到本状态'0'需执行的动作
    //构造函数
    grid(int state[9], int parent, string movement)
    {
        for(int i = 0; i < 9; i ++)
                 this->state[i] = state[i];

        this->parent = parent;
        this->movement = movement;
    }       
    grid() {}
    void create_newstate(int dir);
    void Numarry_to_String();
    bool isend();
};
grid start,final;

vector<grid> GList;

void grid::Numarry_to_String()
{
    for(int i = 0; i < 9 ; i ++)
    {
       char ch = state[i] + '0';
       str_state = str_state + ch;
    }
}

bool grid::isend()
{
    for(int i = 0; i < 9; i ++)
       if(state[i] != final.state[i])
            return false;

    return true;
}

map<string,int> HashMap;

bool getNewGrid(grid &nownode,int dir)
{
    int index;
    for(int i = 0; i < 9; i ++)
              if(nownode.state[i] == 0)
                    index = i;
    switch (dir)          
    {
    case -3:  //index向上 i>=3
       if(index >= 3)
          swap(nownode.state[index],nownode.state[index-3]);   
          nownode.Numarry_to_String();
          return true;              
       break;  
    case 3: 
       if(index <= 5) //index向下 i <= 5
           swap(nownode.state[index],nownode.state[index+3]);
           nownode.Numarry_to_String();
           return true;
        break;
    case 1:       //index 向右 i!=2,5,8;
       if(index!=2 && index != 5 && index !=8 )
           swap(nownode.state[index],nownode.state[index+1]);
           nownode.Numarry_to_String();
           return true;
        break;
    case -1: 
        if(index%3 != 0)  //index向左
           swap(nownode.state[index],nownode.state[index-1]);
           nownode.Numarry_to_String();
           return true;
        break;
    default:
        return false;
        break;
    }
}
int MapIndex = 2;
bool bfs()
{
    queue<grid> GridQueue;
    GridQueue.push(start);
    string move[4] = {"up","down","left","right"};
    int dir[4] = {-3,3,-1,1};
    int index = 0;
    while(!GridQueue.empty())
    {
        grid FirstGrid = GridQueue.front();   
        GridQueue.pop();
        for(int i = 0; i < 4; i ++)
        {
            grid NewGrid = grid(FirstGrid.state,FirstGrid.my_index,move[i]);
            if(getNewGrid(NewGrid,dir[i]))
            {
                GList.push_back(NewGrid);
                index ++;
                NewGrid.my_index = index;
                if(NewGrid.isend())
                {
                   stack<grid> path;
                   grid ParentGrid = NewGrid;
                   path.push(ParentGrid);
                   while(ParentGrid.parent != -1)
                   {
                      path.push(GList[ParentGrid.parent]);
                      ParentGrid = GList[ParentGrid.parent];
                   } 
                   //path.push(ParentGrid);
                   int step = 0;
                   while(!path.empty())
                   {
                       grid prinGrid = path.top();
                       path.pop();
                       if(step == 0) cout<<prinGrid.movement<<endl;
                       else 
                            cout<<"step "<<step<<endl;
                       for(int i = 0; i < 9 ; i ++)
                       {    
                           cout<<prinGrid.state[i]<<" ";
                           if(i == 2|| i ==5 || i == 8)
                           cout<<endl;   
                       }
                       step++;
                    }
                    return true;
                }
                if(HashMap.find(NewGrid.str_state) == HashMap.end()) //不存在
                {
                    HashMap.insert(pair<string,int>(NewGrid.str_state,MapIndex));
                    MapIndex ++;
                    GridQueue.push(NewGrid);
                }
            }
        }
    }
    return false;
}
int main()
{
    int n = 9;
    for(int i = 0 ; i < n ; i ++)
    {
        cin>>start.state[i];
    }
    start.parent = -1;
    start.my_index = 0;
    start.movement = "initial";
    start.Numarry_to_String();
    HashMap.insert(pair<string, int>(start.str_state,0));
    GList.push_back(start);
    //char enter;
    //cin>>enter;
    for(int i = 0; i < n ; i ++)
    {
        cin>>final.state[i];
    }
    final.Numarry_to_String();
    HashMap.insert(pair<string,int>(final.str_state,1));
    if(!bfs()) 
         cout<<"no answer";
}

你可能感兴趣的:(算法,算法)