UVa 1604 Cubic Eight-Puzzle 双方向 BFS ステータス設定

質問リンク: Cubic Eight-Puzzle
質問の説明:

初期状態と終了状態が3*3 3*3であると仮定します。33グリッド、グリッドには8 88 個の立方体と空白の場合、各立方体の色は次のとおりです。
ここに画像の説明を挿入します
終端状態の立方体の上方向のみが指定されることに注意してください。立方体の初期配置は次のようになります。空白の位置は次のとおりです。 2つの入力で決まる 整数で決まる:
ここに画像の説明を挿入します
操作するたびに、初期状態の立方体を空白スペースに押し込むことができます 押し込む過程で回転が発生します 処理は下図のようになります

3030になる30ステップ以内で目標状態に到達します。

答え:

この質問の考え方は非常にシンプルで、双方向のBFS BFSを使用できます。BFS では、各非空間正方形には 6 つの状態 (6 つの表が上に相当) があるため、4 桁のバイナリを使用して合計 9 つのグリッドを表すことができるため、36 36 が必要になります状態を表す36ビットのバイナリ。ターゲット状態の両側が不確実であるため、各側は 2 つの状況に対応します。最初にすべての可能なターゲット状態をキューに入れ、開始状態から検索する必要があります。なお、双方向 BFSBFSBFS は、検索するたびに小さいキューを選択する必要があります。検索数は、1 つのキューの最後まで検索するのではなく、選択したキューの現在のサイズになります。
この質問には詳細な内容が多いため、回転後の状態に注意する必要があります。
同時に、この質問はSTL STLST Lは定数が大きくタイムアウトしやすいので注意が必要です。

コード:

#include <bits/stdc++.h>

const int MAXN = 9;

using namespace std;

typedef pair<int, long long> State;

int x, y, ans;
long long endStatus, initStatus;
long long status[MAXN];
string s[MAXN];
queue<State> q[2];
unordered_map<long long, int> inQ, dis;


void getStatus(string &s, vector<int> &status)
{
    
    
    if (s[0] == 'E') {
    
    
        status.push_back(0);
    } else if (s[0] == 'W') {
    
    
        status.push_back(1);
        status.push_back(2);
    } else if (s[0] == 'R') {
    
    
        status.push_back(3);
        status.push_back(4);
    } else if (s[0] == 'B') {
    
    
        status.push_back(5);
        status.push_back(6);
    }
}

void initEndStatus(int p)
{
    
    
    if (p == 9) {
    
    
        endStatus = 0;
        for (int i = 0; i < 9; i++) {
    
    
            endStatus |= status[i] << (4 * i);
        }
        inQ[endStatus] = 1;
        dis[endStatus] = 0;
        q[1].push({
    
    0, endStatus});
        return;
    }
    vector<int> v;
    getStatus(s[p], v);
    for (int nowStatus : v) {
    
    
        status[p] = nowStatus;
        initEndStatus(p + 1);
    }
}

long long getInitStatus()
{
    
    
    long long initStatus = 0;
    for (int i = 0; i < 9; i++) {
    
    
        if (i / 3 == x && i % 3== y) {
    
     continue; }
        initStatus |= 1LL << (4 * i);
    }
    return initStatus;
}

void init()
{
    
    
    while (!q[0].empty()) {
    
     q[0].pop(); }
    while (!q[1].empty()) {
    
     q[1].pop(); }
    inQ.clear();
    dis.clear();
    initStatus = getInitStatus();
    initEndStatus(0);
}

void getEmptyPos(long long status, int &x, int &y)
{
    
    
    for (int i = 0; i < 9; i++) {
    
    
        if (((status >> (4 * i)) & (0b1111)) == 0) {
    
    
            x = i / 3;
            y = i % 3;
            break;
        }
    }
}

// 获取x, y位置的状态
long long getStatus(long long status, int x, int y)
{
    
    
    return (status >> (4 * (3 * x + y))) & 0b1111;
}

int dx[] = {
    
    0, 0, 1, -1};
int dy[] = {
    
    1, -1, 0, 0};

long long p[7][4] = {
    
    
    {
    
    0, 0, 0, 0},
    {
    
    5, 5, 3, 3},
    {
    
    4, 4, 6, 6},
    {
    
    6, 6, 1, 1},
    {
    
    2, 2, 5, 5},
    {
    
    1, 1, 4, 4},
    {
    
    3, 3, 2, 2}
};

long long transfer(long long status, int i)
{
    
    
    int x = 0, y = 0;
    getEmptyPos(status, x, y);
    int nx = x + dx[i];
    int ny = y + dy[i];
    if (nx < 0 || nx > 2 || ny < 0 || ny > 2) {
    
     return -1; }
    int lasP = 3 * x + y;
    int newP = 3 * nx + ny;
    long long newStatus = status;
    newStatus ^= getStatus(status, nx, ny) << (4 * newP); // 将nx, ny变为空格
    newStatus |= p[getStatus(status, nx, ny)][i] << (4 * lasP); // 将x, y填入新的状态
    return newStatus;
}

int bfs(queue<State> &q, int nowQ)
{
    
    
    int size = q.size();
    while (size--) {
    
    
        State now = q.front();
        q.pop();
        if (now.first >= 30) {
    
     continue; }
        for (int i = 0; i < 4; i++) {
    
    
            State newState;
            newState.first = now.first + 1;
            newState.second = transfer(now.second, i);
            if (newState.second == -1) {
    
     continue; }
            if (inQ.count(newState.second)) {
    
    
                if (inQ[newState.second] == 1 - nowQ) {
    
    
                    ans = dis[newState.second] + now.first + 1;
                    if (ans > 30) {
    
     ans = -1; }
                    return 0;
                } else {
    
    
                    continue;
                }
            }
            dis[newState.second] = newState.first;
            inQ[newState.second] = nowQ;
            q.push(newState);
        }
    }
    return -1;
}

void dBfs()
{
    
    
    if (inQ.count(initStatus)) {
    
    
        ans = 0;
        return;
    }
    ans = -1;
    inQ[initStatus] = 0;
    dis[initStatus] = 0;
    q[0].push({
    
    0, initStatus});
    while (!q[0].empty() && !q[1].empty()) {
    
    
        if (q[0].size() <= q[1].size()) {
    
    
            if (bfs(q[0], 0) == 0) {
    
     return; }
        } else {
    
    
            if (bfs(q[1], 1) == 0) {
    
     return; }
        }
    }
}

int main()
{
    
    
    while (cin >> x >> y && (x != 0 || y != 0)) {
    
    
        x--;
        y--;
        swap(x, y); // 习惯横着编号
        for (int i = 0; i < 9; i++) {
    
     cin >> s[i]; }
        init();
        dBfs();
        cout << ans << endl;
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/qq_45523675/article/details/129209960