You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10; // 开小了会WA
unordered_map<string, int> dist; // 记录某个字符串,走没有走过,如果走过,那么是走了几步到达的
unordered_map<string, pair<char, string>> pre; // 记录某个字符串它的前序操作符是ABC中的哪一个它的前序字符串是什么
string start = "12345678"; // 起始态
string ed; // 目标态,需要输入进来
string q[N]; // 队列
// 交换上下两行
string A(string t) {
// 1234 5678---> 8765 4321
for (int i = 0; i < 4; i++) swap(t[i], t[7 - i]);
return t;
}
// 将最右边的一列插入到最左边
string B(string t) {
// 1234 5678 ---> 4123 6785
// 4向上冒泡,5向后冒泡
for (int i = 3; i > 0; i--) swap(t[i], t[i - 1]);
for (int i = 4; i < 7; i++) swap(t[i], t[i + 1]);
return t;
}
// 魔板中央的4个数作顺时针旋转
string C(string t) {
// 1234 5678 ---> 1724 5368
/*
swap(t[1], t[2]) 1234 5678 -> 1324 5678 把第一个不匹配的数字放到合适位置上
swap(t[5], t[6]) 1324 5678 -> 1324 5768 把第二个不匹配的数字放到合适位置上
swap(t[1], t[5]) 1324 5768 -> 1724 5368 回到头,再把第一个不匹配的数字放到合适位置上
*/
swap(t[1], t[2]), swap(t[5], t[6]), swap(t[1], t[5]);
return t;
}
void bfs() {
int hh = 0, tt = -1;
q[++tt] = start; // 起始点入队列
while (hh <= tt) {
string t = q[hh++];
if (t == ed) return; // 终点
string m[3] = {A(t), B(t), C(t)}; // 按ABC操作后产生的三种字符串
for (int i = 0; i < 3; i++) {
string x = m[i];
if (!dist.count(x)) { // 没有走过
q[++tt] = x;
dist[x] = dist[t] + 1;
pre[x] = {'A' + i, t}; // x的前序t,是通过'A'+i方式转化过来的
}
}
}
}
int main() {
char x;
for (int i = 0; i < 8; i++) cin >> x, ed += x; // 拼接终止状态字符串
// 广搜
bfs();
// 输出距离
cout << dist[ed] << endl;
// 输出路径
string res;
// 如果操作序列的长度大于0则在第二行输出字典序最小的操作序列。
if (dist[ed]) {
while (true) {
if (ed == start) break;
res += pre[ed].first; // 前序操作符,拼接路径,是反的,因为从最后的状态出发,找前序
ed = pre[ed].second; // 前序字符串
}
for (int i = res.size() - 1; i >= 0; i--) cout << res[i];
}
return 0;
}