NC17872(bfs+状压)

最终状态是除了障碍物所有的点都要经过,要求最少步数,可以考虑bfs,dist[x1][y1][x2][y2]无法表示全部状态,所以还需要加上一维表示现在的状态,数据范围小,可以使用状态压缩。

#include <bits/stdc++.h>
using namespace std;
int n, m;
const int N = 5;
char g[N][N];
int sx, sy;
int dis[1 << 16][N][N][N][N];
struct T {
    int st;
    int x1, y1, x2, y2;
};
int s;
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
int cal(int x, int y) {
    return 1 << (x * m + y);//下标从0开始可以使用这个小技巧把二维压缩成一维,然后看哪个点被遍历这个点的状态就是1;
}
int bfs(int state) {
    queue<T> q;
    memset(dis, -1, sizeof dis);
    T start = {s, sx, sy, sx, sy};
    dis[s][sx][sy][sx][sy] = 0;
    q.push(start);
    while (q.size()) {
        auto t = q.front();
        if (t.st == state) return dis[t.st][t.x1][t.y1][t.x2][t.y2];
        q.pop();
        for (int i = 0; i < 4; i++) {
            int atx = t.x1 + dx[i], aty = t.y1 + dy[i];
            if (atx<0 or atx>=n or aty<0 or aty>=m or g[atx][aty] == 'X') continue;
            for (int j = 0; j < 4; j++) {
                int btx = t.x2 + dx[j], bty = t.y2 + dy[j];
                if (btx<0 or btx>=n or bty>=m or bty<0 or g[btx][bty] == 'X') continue;
                int nst = t.st | cal(atx, aty) | cal(btx, bty);
                if (dis[nst][atx][aty][btx][bty] ==-1) {
                    dis[nst][atx][aty][btx][bty] = dis[t.st][t.x1][t.y1][t.x2][t.y2] + 1;
                    q.push({nst, atx, aty, btx, bty});
                }
            }
        }
    }
    return -1;
}
int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++) cin >> (g[i]);
    int state = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (g[i][j] == 'S') sx = i, sy = j, s |= cal(i, j);
            if (g[i][j] == 'S' or g[i][j] == 'O') state |= cal(i, j);
        }
    }
    printf("%d\n", bfs(state));

    return 0;
}
posted @ 2021-11-15 23:47  指引盗寇入太行  阅读(41)  评论(0编辑  收藏  举报