NC17872 CSL的校园卡

题目链接

题目

题目描述

今天是阳光明媚,晴空万里的一天,CSL早早就高兴地起床走出寝室到校园里转悠。

但是,等到他回来的时候,发现他的校园卡不见了,于是他需要走遍校园寻找它的校园卡。CSL想要尽快地找回他掉的校园卡,于是便求助于OneDay帮他一起找。

OneDay和CSL在同一已知的地点出发,并以相同的速度(1格/秒)搜索校园,试求两人走遍校园的最短时间。

输入描述

第一行为两个整数n,m(1 ≤ n, m ≤ 4),表示地图的大小。接下来是n行m列的地图:X表示障碍物,S表示起点,O表示空地。障碍物不能直接经过,数据保证所有空地是可达的,起点有且只有一个。

输出描述

输出一个整数表示两人共同走遍校园所需的最少时间。

示例1

输入

3 4
XSOO
OOXO
OOOO

输出

5

说明

img

示例2

输入

2 3
XSX
OOO

输出

2

示例3

输入

4 4
SOOO
OOOO
OOOO
OOOO

输出

8

题解

知识点:BFS。

和通常走迷宫状态是坐标不同,这次是具体的两人坐标加上抽象的局面状态一共五维,每维都是互相独立的。

将局面状态压缩成一个整数,先将二维坐标压缩成一维 \(i*n+j\) ,再将这个坐标压缩进状态 \(1<<(i*n+j)\) ,于是实现了状态压缩。

每次扩展都是把两人 \(16\) 种方向组合都枚举一遍。

直到当前局面和目标局面相等则输出步数。

时间复杂度 \(O(?)\)

空间复杂度 \(O(m^2n^22^{mn})\)

代码

#include <bits/stdc++.h>

using namespace std;

int n, m;
char dt[4][4];
const int dir[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
int fin;
bool vis[4][4][4][4][1 << 16];
struct node {
    int x1, y1, x2, y2, state, step;
};

int bfs(node st) {
    queue<node> q;
    q.push(st);
    vis[st.x1][st.y1][st.x2][st.y2][st.state] = 1;
    while (!q.empty()) {
        node cur = q.front();
        q.pop();
        if (cur.state == fin) return cur.step;
        for (int i = 0;i < 4;i++) {
            for (int j = 0;j < 4;j++) {
                int xx1 = cur.x1 + dir[i][0];
                int yy1 = cur.y1 + dir[i][1];
                int xx2 = cur.x2 + dir[j][0];
                int yy2 = cur.y2 + dir[j][1];
                int sstate = cur.state | (1 << (xx1 * 4 + yy1)) | (1 << (xx2 * 4 + yy2));
                if (xx1 < 0 || xx1 >= n || yy1 < 0 || yy1 >= m) continue;
                if (xx2 < 0 || xx2 >= n || yy2 < 0 || yy2 >= m) continue;
                if (dt[xx1][yy1] == 'X' || dt[xx2][yy2] == 'X') continue;
                if (vis[xx1][yy1][xx2][yy2][sstate]) continue;
                vis[xx1][yy1][xx2][yy2][sstate] = 1;
                q.push({ xx1,yy1,xx2,yy2,sstate,cur.step + 1 });
            }
        }
    }
    return -1;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> m;
    node st;
    for (int i = 0;i < n;i++) {
        for (int j = 0;j < m;j++) {
            cin >> dt[i][j];
            if (dt[i][j] == 'S') st = { i,j,i,j,1 << (i * 4 + j),0 };
            if (dt[i][j] != 'X') fin |= 1 << (i * 4 + j);
        }
    }
    cout << bfs(st) << '\n';
    return 0;
}
posted @ 2022-07-16 19:29  空白菌  阅读(49)  评论(0编辑  收藏  举报