zoukankan      html  css  js  c++  java
  • 题解【洛谷P2730】魔板 Magic Squares

    题面

    首先我们可以发现,在每一次 BFS 时按照 (A→B→C) 的顺序枚举遍历肯定是字典序最小的。

    然后就是普通的 BFS 了。

    我们考虑使用 ( ext{STL map}) 来存储起点状态到当前状态所需的最少步数,以及到达它的上一个状态与上一个操作代号。

    具体实现可参考代码。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int n, m;
    string start = "12345678", endd; //起始状态和目标状态
    map <string, int> dist; //存储到达当前状态的最少步数
    map <string, pair <char, string> > ans; //到达当前状态的上一个状态和操作代号
    string q[100003], sum; //BFS 时的队列 和 答案
    int hh, tt; //队头和队尾指针
    char g[3][5]; //临时矩阵,转移的时候用
    
    inline void getjuzhen(string x) //从压缩的状态变成矩阵
    {
        for (int i = 1; i <= 4; i+=1) g[1][i] = x[i - 1]; //第一排
        g[2][4] = x[4], g[2][3] = x[5], g[2][2] = x[6], g[2][1] = x[7]; //第二排
    }
    
    inline string getzhuangtai() //从矩阵压缩成状态
    {
        string now = "";
        for (int i = 1; i <= 4; i+=1) now = now + g[1][i]; //第一排
        for (int j = 4; j >= 1; j-=1) now = now + g[2][j]; //第二排
        return now;
    }
    
    inline string getA(string x) //A 操作
    {
        getjuzhen(x);
        for (int i = 1; i <= 4; i+=1) swap(g[1][i], g[2][i]); //将第一行与第二行交换
        return getzhuangtai();
    }
    
    inline string getB(string x) //B 操作
    {
        getjuzhen(x);
        swap(g[1][1], g[1][4]), swap(g[2][1], g[2][4]);
        swap(g[1][2], g[1][4]), swap(g[2][2], g[2][4]);
        swap(g[1][3], g[1][4]), swap(g[2][3], g[2][4]);
        //依次交换每一列
        return getzhuangtai();
    }
    
    inline string getC(string x) //C 操作
    {
        getjuzhen(x);
        swap(g[1][2], g[1][3]);
        swap(g[1][2], g[2][3]);
        swap(g[1][2], g[2][2]);
        //中间的 4 个数依次交换
        return getzhuangtai();
    }
    
    inline void bfs(string s, string t) //BFS
    {
        if (s == t) return; //如果目标状态与开始状态相同就不要搜索了
        hh = tt = 0;
        q[0] = s; //队列中只有 1 个元素
        while (hh <= tt) //队列不为空
        {
            string c = q[hh++]; //取出队头元素
            string h[3];
            h[0] = getA(c); //A 操作
            h[1] = getB(c); //B 操作
            h[2] = getC(c); //C 操作
            for (int i = 0; i < 3; i+=1) //枚举每一个操作
            {
                if (dist[h[i]] == 0) //如果当前状态还没有遍历过
                {
                    dist[h[i]] = dist[c] + 1; //记录最少步数
                    ans[h[i]] = (make_pair)(i + 'A', c); //记录转移过来的操作代号和状态
                    if (h[i] == t) return; //找到了目标状态
                    q[++tt] = h[i]; //加入队列
                }
            }
        }
    }
    
    int main()
    {
        for (int i = 1; i <= 8; i+=1)
        {
            int u; cin >> u;
            endd = endd + (char)(u + '0'); //目标状态
        }
        bfs(start, endd); 
        cout << dist[endd] << endl; //输出最少步数
        if (dist[endd] == 0) return 0; //注意特判
        while (endd != start) //推出每一步的操作
        {
            sum = sum + ans[endd].first; //记录每一步的操作
            endd = ans[endd].second; //向前推
        }
        reverse(sum.begin(), sum.end()); //记得要反转,因为我们存储的操作是反序的
        cout << sum << endl; //输出操作序列
        return 0;
    }
    
  • 相关阅读:
    asp.net MVC 3/4 equivalent to a response.filter
    Asp.net MVC Request Life Cycle
    无法完成你的itunes store 请求发生未知错误50
    苹果Mac OS X系统十三年视觉变化发展史
    authentication not supported Connect to TFS Git from Xamarin Studio (non-hosted, locally installed TFS 2013)
    iOS开发者帐号申请指南
    Apple Developer Registration and DUNS Number Not Accepted
    apple developer D-U-N-S® Number
    苹果企业开发者账号申请记录
    D-U-N-S申请流程
  • 原文地址:https://www.cnblogs.com/xsl19/p/12373046.html
Copyright © 2011-2022 走看看