2018拼多多内推编程题:带key的迷宫+很棒的做法

链接:https://www.nowcoder.com/questionTerminal/e3fc4f8094964a589735d640424b6a47
来源:牛客网
作者:超蓝の悟空

时间限制:1秒
空间限制:131072K

假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙

输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N
后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。

输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N
后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。

输出描述:
路径的长度,是一个整数

输入例子1:
5 5
02111
01a0A
01003
01001
01111

输出例子1:
7

注意这个是一个长方形的迷宫,我起初太傻了以为是一个正方形的迷宫。这个简单错误不能再犯了

首先这道题是在一个矩阵中寻找最短路径,所以肯定是BFS广度优先遍历,但是key和door的关系我当时没想清楚。

后来网上看到了别人的一个做法,感觉很简单,看来我对BFS的理解还有点不够透彻。这道题的visit[x][y][key]的意义就是横坐标为x,纵坐标为y,钥匙状态为key的点是否访问过。钥匙的状态 就用二进制数表示 最多10 把钥匙 那就是1024,比如我现在有第二把钥匙和第四把钥匙 那么我的钥匙状态就是 0101000000 也就是 320,注意提议中说了最多十把钥匙,也即使用10bit即可表示所有状态,状态数量最大是1024。

经过上述的分析题目就很简单了。

#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <string>
#include <climits>
#include <algorithm>
#include <sstream>
#include <functional>
#include <bitset>
#include <numeric>
#include <cmath>
#include <regex>
#include <iomanip>
#include <cstdlib>
#include <ctime>

using namespace std;


class Point
{
public:
    int x, y, key, step;
    Point(int xx, int yy,int k,int s)
    {
        x = xx;
        y = yy;
        key = k;
        step = s;
    }
};


int bfs(vector<vector<char>>& a, int startx,int starty)
{
    queue<Point> que;
    que.push(Point(startx, starty, 0, 0));
    vector<vector<int>> dir{ { -1,0 },{ 1,0 },{ 0,1 },{ 0,-1 } };
    int visit[105][105][1200] = { 0 };

    while (que.empty() == false)
    {
        auto top = que.front();
        que.pop();

        //这个放到循环中会出现超时的问题
        if (a[top.x][top.y] == '3')
            return top.step;

        for (auto d : dir)
        {
            int x = top.x + d[0], y = top.y + d[1];
            if (x < 0 || x >= a.size() || y < 0 || y >= a[0].size() || a[x][y] == '0')
                continue;

            //遇到钥匙去做添加
            int key = top.key;
            if (a[x][y] >= 'a' && a[x][y] <= 'z')
                key = (key | (1 << (a[x][y] - 'a')));

            //遇到门去找钥匙
            if(a[x][y] >= 'A' && a[x][y] <= 'Z' && (key&(1 << (a[x][y] - 'A'))) == 0)
                continue;

            //在x和y位置的地方由于key是否访问过
            if (visit[x][y][key] == 0)
            {
                visit[x][y][key] = 1;
                que.push(Point(x, y, key, top.step + 1));
            }
        }
    }
    return 0;
}

int main()
{
    int n,m;
    cin >> n>>m;
    int x, y;
    vector<vector<char>> all(n, vector<char>(m));

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cin >> all[i][j];
            if (all[i][j] == '2')
            {
                x = i;
                y = j;
            }
        }
    }
    int res=bfs(all, x, y);
    cout << res << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jackzhang_123/article/details/79628192
今日推荐