LCEZ2.18 开学测试 T3 密室逃脱 题解

题目描述

即使 Czhou 没有派出最强篮球阵容,机房篮球队还是暴虐了校篮球队。为了不打击校篮球队信心, Czhou 决定改变训练后的活动。近来,江大掌门的徒弟徒孙们纷纷事业有成,回到母校为机房捐钱捐物。财大气粗的机房组收回了五层六层的所有教室。 Czhou 决定将六层的教室改造为智能密室逃脱活动室。

每天傍晚,神牛们可以依次逐个进入游玩。我们简单的将教室分割为 \(n×n\) 个房间,\(K\) 是你初始所在房间,\(T\) 是你最终逃脱的房间。如果你想要逃脱房间,你必须依次找到m把钥匙。我们假定你从一个房间进入另一个房间需要花费 1 的时间。当然某些房间有些特殊的问题(地图上 \(S\) 表示)需要回答才能通过,对于机智的众牛们来说,这些问题根本不是问题。我们假定众牛们花费 1 的时间解决问题。(主要是出题的人表述不清,导致众牛理解困难;当然问题只需要回答一次,下次再次进入房间不需要回答了)

输入格式

第一行两个数字 \(n\)\(m\)
接下来 \(n×n\) 描述地图

输出格式

需要最少时间逃脱密室。若无解输出 impossible

输入 #1

3 1
K.S
##1
1#T

输出 #1

5

输入 #2

3 1
K#T
.S#
1#.

输出 #2

impossible

输入 #3

3 3
K#T
.S.
21.

输出 #3

8

样例3说明

要先取钥匙1,再取钥匙2。地图上可能有多个同一种钥匙,#为墙壁即不可走。

数据范围

\(0<N\le 100\)\(0\le M\le 9\)\(S\) 很小。

解题思路

考试时这道题没有给 \(S\) 的数据范围,导致这题不可做。

考试时我是依据 \(M\) 枚举的钥匙个数,求出需要跑最短路的次数,之后用 bfs 跑最短路,发现这是错误做法。

正解是通过 \(S\) 用 dfs 枚举走几个问题,之后用 bfs 跑最短路(走迷宫)。

一道非常基础的题,只要思路正确,会基本的深搜、广搜,再注意细节,就很容易切掉了。

代码

/*---------------------------------
 *Title number: T3
 *Creation date: 2021.2.18
 *Author: EdisonBa 
 *-------------------------------*/
#include <头文件>
using namespace std;
typedef long long ll;

inline ll read(){}

const int inf = 100000000;

int ans = inf;
int n, m, cnt, x1, x2, y1, y2;
char a[105][105];
int f[105][105][15];
int qx[100005], qy[100005], qm[100005];
int xx[4] = {0, 0, 1, -1}, yy[4] = {1, -1, 0, 0};
int x[15], y[15];
void bfs()
{
    memset(f, -1, sizeof(f));
    qx[0] = x1;
    qy[0] = y1;
    int head = 0, tail = 1;
    f[x1][y1][0] = 0;
    while (head != tail)
    {
        int x = qx[head], y = qy[head], t = qm[head];
        head++;
        for (int i = 0; i < 4; i++)
        {
            int nowx = x + xx[i], nowy = y + yy[i], nowm = t;
            if (nowx < 1 || nowy < 1 || nowx > n || nowy > n)
                continue;
            if (nowm + 1 == a[nowx][nowy] - '0')
                nowm++;
            if (a[nowx][nowy] == '#' || f[nowx][nowy][nowm] != -1)
                continue;
            f[nowx][nowy][nowm] = f[x][y][t] + 1;
            qx[tail] = nowx;
            qy[tail] = nowy;
            qm[tail] = nowm;
            tail++;
        }
    }
}
void dfs(int now, int k)
{
    if (now == cnt + 1)
    {
        bfs();
        if (f[x2][y2][m] != -1)
            ans = min(ans, k + f[x2][y2][m]);
        return;
    }
    a[x[now]][y[now]] = '.';
    dfs(now + 1, k + 1);
    a[x[now]][y[now]] = '#';
    dfs(now + 1, k);
}
int main()
{
    freopen("maze.in", "r", stdin);
    freopen("maze.out", "w", stdout);
    n = read();
    m = read();
    for (int i = 1; i <= n; i++)
    {
        scanf("%s", a[i] + 1);
        for (int j = 1; j <= n; j++)
            if (a[i][j] == 'K')
            {
                x1 = i;
                y1 = j;
            }
            else if (a[i][j] == 'T')
            {
                x2 = i;
                y2 = j;
            }
            else if (a[i][j] == 'S')
            {
                cnt++;
                x[cnt] = i;
                y[cnt] = j;
            }
    }
    dfs(1, 0);
    if (ans == inf)
        puts("impossible");
    else
        printf("%d\n", ans);
    return 0;
}

2021 CSP-S & NOIP \(RP++\)

原文地址:https://www.cnblogs.com/EdisonBa/p/14416689.html