zoukankan      html  css  js  c++  java
  • BFS:八数码问题

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <set>
    using namespace std;
    
    /*
    2 6 4 1 3 7 0 5 8
    8 1 5 7 3 6 4 0 2
    
    1 2 3 4 5 0 7 8 6
    1 2 3 4 5 6 7 8 0
    */
    typedef int State[9];
    const int maxstate = 1000000;
    State st[maxstate], goal;        //状态数组, 所有状态都保存在这里 
    int dist[maxstate];              //距离数组
    
    set<int> vis;                    //编码 
    //如果需要打印方案,可以在这里加一个"父亲编号" 数组  int fa[maxstate]
    int fa[maxstate];
    
    void init_lookup_table();
    int try_to_insert(int s);
    int BFS();
    void solve();
    
    const int dx[] = {-1, 1, 0, 0};
    const int dy[] = {0, 0, -1, 1};
    
    void print(State s, int front)
    {
        for (int i = 0; i < 9; i++) {
            if (i % 3 == 0) cout << endl;
            cout << st[front][i] << " ";
        }
        cout << endl;
    }
    
    bool judge(int x, int y)
    {
        return (x >= 0 && x < 3) && (y >= 0 && y < 3);
    }
    
    void init_lookup_table()
    {
        for (int i = 0; i < 9; i++) {
            scanf("%d", &st[1][i]);        //起始状态 
        }
        for (int i = 0; i < 9; i++) {
            scanf("%d", &goal[i]);
        }
        vis.clear();
    }
    
    int try_to_insert(int s)
    {
        int code = 0;     //把st[s]映射到code
        for (int i = 0; i < 9; i++) {
            code = code * 10 + st[s][i];
        } 
        if (vis.count(code)) return 0;
        vis.insert(code);
        return 1;         //HashCode 
    }
    
    //BFS, 返回目标状态在st数组下标
    int BFS()
    {
        init_lookup_table();              //初始化查找表 
        int front = 1, rear = 2;          //不使用下标0, 因为0被看作不存在 
        while (front < rear) { 
            State& s = st[front];         //用引用简化代码
            if (memcmp(goal, 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 + dx[d];
                int newy = y + dy[d];
                int newz = newx * 3 + newy; //模拟到一维数组的地方 , 空格将要移动到的地方 
                
                if (judge(newx, newy)) {    //移动合法 
                    State &t = st[rear];    //得到队尾元素
                    memcpy(&t, &s, sizeof(s));    // 将将 s 添加到队尾 
                    
                    //数字 和 空格交换位置  
                    t[newz] = s[z];         //z位置为 空格 
                    t[z] = s[newz];    
                
                    dist[rear] = dist[front] + 1;     //更新新结点的距离值
                    if (try_to_insert(rear))  rear++; //如果成功插入查找表, 修改队尾指针 
                }
            }
            front++;     //拓展完毕, 修改队首指针 
            //打印 
            print(st[front], front);
        }
        return 0;        //失败 
    } 
    
    void solve()
    {
        int ans = BFS();
        if (ans > 0) printf("%d
    ", dist[ans]);
        else printf("-1
    ");
    }
    
    int main()
    {
        solve();
        return 0;    
    }
  • 相关阅读:
    Linux source命令
    pythoy 基础一: python的特点 if 语句 whlie语句
    linux 基础
    python的游戏之旅( 数字 字符串 列表 元组 字典 即为游戏职业)
    html 基础
    《SQL Server 2008 从入门到精通》 学习笔记 第五天
    [转载] Visual Studio 2010 MSDN Help Library文档位置、错误、重新安装及安装注意事项
    ASP.NET后台通过输出JavaScript弹出窗口小结
    网上搜集的webbrower的资料,很有借鉴价值
    解决MSSQL 2008不能用IP登录的问题 和 打开可以用SA登录SQL2008的方法
  • 原文地址:https://www.cnblogs.com/douzujun/p/6665017.html
Copyright © 2011-2022 走看看