• HDU1043 八数码(BFS + 打表)


      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 , 康托展开 + BFS + 打表。

      经典八数码问题,传说此题不做人生不完整,关于八数码的八境界:http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html

      我自己是用哈希(康托展开) + BFS  + 打表过的,第三重境界。

      由于一些高级的搜索现在还没学,所以目前能升级的也就是用双向BFS来做了,等过几天有心情了来做。

      本文长期更新。


    算法:  

      由于此题是求某个起始状态到“12345678X”的步骤,所以可以考虑先求出“12345678X”的所有变换的步骤,即打表预处理。

      这里要注意就是最后输出的时候,由于我们求得是逆序,所以要倒序输出,倒序输出的时候要注意'u'、'd'、'l'、'r'都应该颠倒过来,比如说你从A状态向上变换为B状态,这时你从B变为A就要向下变换。

      这里哈希还是用的康托展开,这个问题我在上一篇博客中有提到过。

    BFS + 打表:

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <string>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define LL __int64
    #define eps 1e-8
    #define INF 1e8
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int MOD = 2333333; 
    const int maxn = 362880;
    bool vis[maxn];
    string ans[maxn];
    int fac[]={1 , 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320 , 362880};
    
    int Cantor(string str)
    {
        int ret = 0;
        int n = str.size();
        for(int i = 0 ; i < n ; i++) {
            int cnt = 0;
            for(int j = i ; j < n ; j++)
                if(str[j] < str[i])
                    cnt++;
            ret += cnt * fac[n - i - 1];
        }
        return ret;
    }
    void move_Up(string &str , int pos)
    {
        swap(str[pos] , str[pos - 3]);
    }
    void move_Down(string &str , int pos)
    {
        swap(str[pos] , str[pos + 3]);
    }
    void move_Left(string &str , int pos)
    {
        swap(str[pos] , str[pos - 1]);
    }
    void move_Right(string &str , int pos)
    {
        swap(str[pos] , str[pos + 1]);
    }
    void BFS(string start)
    {
        memset(vis , 0 , sizeof(vis));
        queue <string> que;
        que.push(start);
        int x = Cantor(start);
        vis[x] = 1;
        ans[x] = "";
        int pos;
        while(!que.empty()) {
            string u = que.front();
            que.pop();
            int i = Cantor(u);
            for(pos = 0 ; pos < 9 ; pos++)
                if(u[pos] == 'x')
                    break;
    
            if(pos > 2) {
                string tmp = u;
                move_Up(tmp , pos);
                int k = Cantor(tmp);
                if(!vis[k]) {
                    vis[k] = 1;
                    que.push(tmp);
                    ans[k] = ans[i] + 'u';
                }
            }
            if(pos < 6) {
                string tmp = u;
                move_Down(tmp , pos);
                int k = Cantor(tmp);
                if(!vis[k]) {
                    vis[k] = 1;
                    que.push(tmp);
                    ans[k] = ans[i] + 'd';
                }
            }
            if(pos % 3 != 0) {
                string tmp = u;
                move_Left(tmp , pos);
                int k = Cantor(tmp);
                if(!vis[k]) {
                    vis[k] = 1;
                    que.push(tmp);
                    ans[k] = ans[i] + 'l';
                }
            }
            if(pos % 3 != 2) {
                string tmp = u;
                move_Right(tmp , pos);
                int k = Cantor(tmp);
                if(!vis[k]) {
                    vis[k] = 1;
                    que.push(tmp);
                    ans[k] = ans[i] + 'r';
                }
            }    
        }
    }
    int main() 
    {
        char ch[30];
        string start = "12345678x";
        BFS(start);
        while(gets(ch))
        {
            string str = "";
            for(int i = 0 ; ch[i] != '' ; i++) {
                if(ch[i] == ' ')
                    continue;
                else
                    str += ch[i];
            }
            int k = Cantor(str);
            if(vis[k]) {
                for(int i = ans[k].size() - 1 ; i >= 0 ; i--) {
                    if(ans[k][i] == 'u')
                        putchar('d');
                    else if(ans[k][i] == 'd')
                        putchar('u');
                    else if(ans[k][i] == 'l')
                        putchar('r');
                    else
                        putchar('l');
                }
                puts("");
            } else {
                cout << "unsolvable" << endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    函数数组
    编译和链接
    线程详解
    linux内核完全剖析——基于0.12内核-笔记(2)-统一编址和独立编址
    linux内核完全剖析——基于0.12内核-笔记(1)-CPU 数据通信
    input子系统事件处理层(evdev)的环形缓冲区【转】
    NFC驱动调试
    little kernel 小结
    Linux 设备树的解释
    Android中SELinux的TE简介【转】
  • 原文地址:https://www.cnblogs.com/H-Vking/p/4346900.html
Copyright © 2020-2023  润新知