← 返回题目页

A2140 魔板

标程

#include <bits/stdc++.h>
using namespace std;

// s 的下标 0..3 是上排从左到右,4..7 是下排从右到左(顺时针读法)
string applyOp(const string &s, char op) {
    string t(8, '0');
    if (op == 'A') {
        for (int i = 0; i < 8; i++) t[i] = s[7 - i];      // 交换上下两行
    } else if (op == 'B') {
        const int idx[8] = {3, 0, 1, 2, 5, 6, 7, 4};     // 最右一列移到最左
        for (int i = 0; i < 8; i++) t[i] = s[idx[i]];
    } else {
        const int idx[8] = {0, 6, 1, 3, 4, 2, 5, 7};     // 中央顺时针旋转
        for (int i = 0; i < 8; i++) t[i] = s[idx[i]];
    }
    return t;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string target;
    for (int i = 0; i < 8; i++) {
        int x;
        cin >> x;
        target += char('0' + x);
    }

    const string start = "12345678";
    unordered_map<string, pair<string, char>> pre;   // 状态 -> (前驱状态, 使用的操作)
    queue<string> q;
    pre[start] = {"", 0};
    q.push(start);
    while (!q.empty()) {
        string s = q.front();
        q.pop();
        if (s == target) break;
        for (char op = 'A'; op <= 'C'; op++) {   // 按字典序扩展,保证最短且字典序最小
            string t = applyOp(s, op);
            if (pre.count(t)) continue;
            pre[t] = {s, op};
            q.push(t);
        }
    }

    string path, cur = target;
    while (cur != start) {
        path += pre[cur].second;
        cur = pre[cur].first;
    }
    reverse(path.begin(), path.end());
    cout << path.size() << '\n' << path << '\n';
    return 0;
}

动画演示