IMUSTACM_1242

题目描述
小Q被邪恶的大魔王困在了迷宫里,小L决定去解救她。迷宫里面有一些陷阱,一旦走到陷阱里,就会被困身亡 T_T,迷宫里还有一些古老的传送阵,一旦走到传送阵上,会强制被传送到传送阵的另一头。
现在请你帮助小L算一算,他至少需要走多少步才能解救到小Q? (上下左右四个方向走,传送门可以多次使用)

输入
第一行为一个整数T,表示测试数据组数。每组测试数据第一行为两个整数N,M,(1 <= N, M <= 50)表示迷宫的长和宽。接下来有N行,每行M个字符,是迷宫的具体描述。
'.‘表示安全的位置,’#'表示陷阱,'Q’表示小Q的位置,‘L’表示小L所在的位置,数据保证小L只有一个,小Q也只有一个。小写字母’a’-'z’分别表示不同的传送阵,数据保证传送阵两两配对。

输出
每组数据输出一行,解救小Q所需的最少步数,如果无论如何都无法救小Q,则输出-1。

样例输入

2
5 5
…L
.###.
b#b#a
##.##
…Qa
5 5
…L
.###.
.#.#.
##.##
…Q.

样例输出

3
-1

思路:被坑了好久,就是遇到传送门一定要传送,不能当一条路走过去还有就是传送可以多次,我们只标记一次的门即可,因为是直接传送,所以传回去就算标记了也不会不能进队列(脑子模拟模拟)
还有就是刚开始一直过样例但是提交WA,直到看到一个博客的样例
…#.a

.#Q#.

.#.#.

…aL.
原博客https://blog.csdn.net/llzhh/article/details/51907637
解题代码:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <map>
#include <string.h>
#include <queue>
#define ll long long
using namespace std;
int n, m;
char maps[55][55];
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
struct node
{
    int x;
    int y;
    int step;
    friend bool operator<(const node &a,const node &b)
    {
        return a.step > b.step;
    }
};
int bfs(int x,int y)
{
    priority_queue<node>f_l;
    f_l.push({x,y,0});
    int mark[55][55];
    memset(mark,1,sizeof(mark));
    mark[x][y] = 0;
    while(!f_l.empty())
    {
        node a = f_l.top();
        f_l.pop();
 
        //cout << a.x << a.y << endl;
        if(maps[a.x][a.y] == 'Q')
            return a.step;
        for(int k = 0;k < 4;k++)
        {
            int x1 = a.x + dir[k][0];
            int y1 = a.y + dir[k][1];
 
            if(x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && mark[x1][y1] && maps[x1][y1] != '#')
            {
                mark[x1][y1] = 0;//每次标记第一次的传送门,因为直接传过去后的坐标做加减,所以后一个传送门不会被标记;
                if(maps[x1][y1] >= 'a' && maps[x1][y1] <= 'z')
                {
                    bool mark = false;
                    for(int k = 0;k < n;k++)
                    {
                        if(mark)//当赋值后不break就会遇到字母再赋值(因为x1,y1值已经改变,在遇到会又被k,h赋值回去)
                            break;
                        for(int h = 0;h < m;h++)
                        {
                            if(maps[x1][y1] == maps[k][h] && (x1 != k || y1 != h))
                            {
                                x1 = k;
                                y1 = h;
                                mark = true;
                                //cout << k << h << endl;
                            }
                            if(mark)
                                break;
                        }
                    }
                }
                f_l.push({x1,y1,a.step + 1});
            }
        }
    }
    return -1;
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        cin >> n >> m;
        int x, y;
        for(int k = 0;k < n;k++)
        {
            for(int h = 0;h < m;h++)
            {
                cin >> maps[k][h];
                if(maps[k][h] == 'L')
                {
                    x = k;
                    y = h;
                }
            }
        }
       cout << bfs(x,y) << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值