📜  门|门CS 2011 |问题 17(1)

📅  最后修改于: 2023-12-03 15:12:47.442000             🧑  作者: Mango

题目17:门|门CS 2011

题目描述:

在一个城市里,有一些门需要打开才能通过。门的状态是不同的,有的门可以直接打开,有的门需要钥匙才能打开。每个人都有一把钥匙,但是钥匙只能开一扇门。这个城市的地图信息存在一个矩阵里,地图中,1代表可以直接通过的门,0代表需要钥匙才能通过的门,S代表起点,E代表终点,'.'代表可以直接通过的空地。假设有一个人位于起点,能否到达终点?

注意:

  • 钥匙必须是从0位置开始移动到其他位置才可以使用。
  • 步数限制在2000以内。
  • 所有样例数据都保证有解。
输入格式:
  • 第一行为两个整数,表示地图的长和宽。
  • 接下来的n行,每行m个字符,表示地图上的格子。
输出格式:

如果可以到达终点,输出"YES",否则输出"NO"。

输入样例:
5 5
0 S . 1 0
1 . 0 . 1
0 . 1 0 0
1 . E 1 1
0 1 0 . 0
输出样例:
YES
时间限制:
  • C/C++语言:1000MS。
  • 其他语言:2000MS。
  • 内存限制:65536KB。

解题思路

可以用BFS遍历整个地图,需要记录当前位置、当前拥有的钥匙以及已经走过的步数,如果当前位置为终点,则返回“YES”,否则继续搜索。遇到门时,如果拥有钥匙则直接通过,否则需要先回到之前拾取钥匙的位置再获取钥匙。

代码实现

#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
const int N = 25;

int n, m;
char g[N][N];
bool st[N][N][1 << 6];

typedef struct node{
    int x, y, status, step;
}node;
// 上下左右方向的坐标增量
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

int bfs(int sx, int sy){
    queue<node> q;
    node cur;
    cur.x = sx, cur.y = sy, cur.status = 0, cur.step = 0;
    q.push(cur);
    st[sx][sy][0] = true;

    while(q.size()){
        cur = q.front();
        q.pop();

        if(g[cur.x][cur.y] == 'E') return cur.step;

        for(int i = 0; i < 4; i++){
            int nx = cur.x + dx[i], ny = cur.y + dy[i];
            int status = cur.status;

            if(nx < 0 || nx >= n || ny < 0 || ny >= m || g[nx][ny] == '#') continue;

            // 门
            if(g[nx][ny] >= 'A' && g[nx][ny] <= 'F' && !(status >> (g[nx][ny] - 'A') & 1)) continue;

            // 钥匙
            if(g[nx][ny] >= 'a' && g[nx][ny] <= 'f') status |= 1 << (g[nx][ny] - 'a');

            if(!st[nx][ny][status]){
                node next_node;
                next_node.x = nx, next_node.y = ny, next_node.status = status, next_node.step = cur.step + 1;
                q.push(next_node);
                st[nx][ny][status] = true;
            }
        }
    }
    return -1;
}

int main(){
    int sx, sy;
    cin >> n >> m;
    memset(st, false, sizeof(st));
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            cin >> g[i][j];
            if(g[i][j] == 'S') sx = i, sy = j;
        }
    }
    cout << (bfs(sx, sy) == -1 ? "NO" : "YES") << endl;
    return 0;
}
  • 时间复杂度:O(nm*(2^k)),其中k为钥匙的数量。
  • 空间复杂度:O(nm*(2^k)),其中k为钥匙的数量。