zoukankan      html  css  js  c++  java
  • 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++\)

  • 相关阅读:
    [算法] 归并排序(自顶向下、自底向上)
    [算法] 快速排序(单路、双路、三路)
    [算法] O(nlogn)和O(n^2)算法性能比较
    [算法] O(n^2)算法的效率比较
    [设计模式] 设计模式课程(十九)--职责链模式
    [OS] 汇编语言
    [c++] 内存模型
    [c++] 内存与变量
    [Qt] 基本概念
    42. Trapping Rain Water
  • 原文地址:https://www.cnblogs.com/EdisonBa/p/14416689.html
Copyright © 2011-2022 走看看