AcWing 1107. 魔板(状态图搜索、输出字典序最小路径)

题目链接:点击这里

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
状态怎么存?字符串

怎么判重?基于哈希的unordered_map记录最短距离的同时进行判重

状态怎么转移?一维字符串转换成二维数组,对二维数组按要求进行转换,再转回字符串

怎么记录路径?使用unordered_map记录到达每个状态所采取的操作及其前一个状态,然后倒着往回推出路径。

#include<iostream>
#include<string>
#include<cstring>
#include<unordered_map>
#include<queue>
#include<algorithm>

using namespace std;

unordered_map<string, int> d;       // 记录每个状态的最短距离
unordered_map<string, pair<char, string>> pre;  // 记录到达每个状态所采取的操作及其前一个状态

int g[2][4];

void str_to_arr(string x)
{
    for(int i = 0; i < 4; ++i)  g[0][i] = x[i] - '0';
    for(int i = 0, j = 7; i < 4; ++i, --j)  g[1][i] = x[j] - '0';
}

string arr_to_str()
{
    string res;
    for(int i = 0; i < 4; ++i)  res += char(g[0][i] + '0');
    for(int i = 3; i >= 0; i--) res += char(g[1][i] + '0');
    return res;
}

string A(string x)
{
    str_to_arr(x);
    
    for(int i = 0; i < 4; ++i)  swap(g[0][i], g[1][i]);
    
    return arr_to_str();
}

string B(string x)
{
    str_to_arr(x);
    
    int a = g[0][3], b = g[1][3];
    g[0][3] = g[0][2], g[1][3] = g[1][2];
    g[0][2] = g[0][1], g[1][2] = g[1][1];
    g[0][1] = g[0][0], g[1][1] = g[1][0];
    g[0][0] = a, g[1][0] = b;
    
    return arr_to_str();
}

string C(string x)
{
    str_to_arr(x);
    
    int a = g[0][1];
    g[0][1] = g[1][1];
    g[1][1] = g[1][2];
    g[1][2] = g[0][2];
    g[0][2] = a;
    
    return arr_to_str();
}

int bfs(string start, string end)
{
    queue<string> q;
    
    q.push(start);
    d[start] = 0;
    
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        
        string a = A(t);                     // A操作
        if(d.count(a) == 0)
        {
            q.push(a);
            d[a] = d[t] + 1;
            pre[a] = {'A', t};
            if(a == end)    return d[a];
        }
        
        string b = B(t);                    // B操作
        if(d.count(b) == 0)
        {
            q.push(b);
            d[b] = d[t] + 1;
            pre[b] = {'B', t};
            if(b == end)    return d[b];
        }
        
        string c = C(t);                    // C操作
        if(d.count(c) == 0)
        {
            q.push(c);
            d[c] = d[t] + 1;
            pre[c] = {'C', t};
            if(c == end)    return d[c];
        }
    }
}

int main()
{
    string start = "12345678", end;
    
    for(int i = 0; i < 8; ++i)
    {
        int x;
        cin>>x;
        end += char(x + '0');
    }
    
    if(start == end)        // 特判
    {
        cout<<"0"<<endl;
        return 0;
    }
    
    cout << bfs(start, end) << endl;
    
    string res;
    while(end != start)
    {
        res += pre[end].first;
        end = pre[end].second;
    }
    
    reverse(res.begin(), res.end());
    
    cout << res << endl;
    return 0;
}
发布了844 篇原创文章 · 获赞 135 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/105079997