UVa 1604 Cubic Eight-Puzzle two-way BFS status setting

Question link: Cubic Eight-Puzzle
question description:

Given an initial state and a terminal state of 3*3 3*333 grid, grid contains8 88 cubes and a blank, the color of each cube is as follows:
Insert image description here
It should be noted that only the top direction of the cube in the terminal state will be given, and the initial cube placement is as shown below, where the blank position is determined by the two input Determined by integers:
Insert image description here
Each time you operate, you can push a cube in the initial state into a blank space. Rotation will occur during the pushing process. The process is as shown in the figure below: Ask if it can be

3030Reach the target state within 30 steps.

answer:

The idea of ​​​​this question is very simple, we can use two-way BFS BFSBFS , each non-space square has six states (corresponding to six faces up), so we can use a four-digit binary to represent a total of nine grids, so36 3636 -bit binary to represent a state. Since the sides of the target state are uncertain, each side corresponds to two situations. We need to initially put all possible target states into the queue, and then search from the starting state. It should be noted that bidirectional BFSBFSBFS should select a smaller queue to search each time. The number of searches is the current size of the selected queue, rather than searching to the end of one queue.
There are many details in this question, so you must be careful about the state after the rotation.
At the same time, this question usesSTL STLFor ST L , the constant is large and it is easy to time out, so you need to pay attention.

Code:

#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;
}

Guess you like

Origin blog.csdn.net/qq_45523675/article/details/129209960