题解 | #maze#

maze

https://ac.nowcoder.com/acm/problem/15665

题目考点:bfs + 优先队列
题目概述:每张地图有起点、终点、陷阱、传送门,求最短时间。注意情况有以下几种:起点有陷阱、传送门终点有陷阱、坐传送门还不如走过去时间短等。前两种问题用数组标记即可;第三种情况用优先队列维护,保证不管是坐传送门还是不开启传送门,到达该点的时间是划算的

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
#define tb std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
ll n, m, t;
ll a1, a2, b1, b2;
char map[310][1010];
ll  smap[1010][1010];
ll dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
struct poss{
    ll x, y, step;
    ll xj, yj;
};
//小根堆优先队列自定义比较器
struct cmp{
    bool operator ()(const poss &x, const poss &y)
    {
        if(x.step >= y.step)return 1;
        return 0;
    }
};
//使用优先队列
priority_queue<poss, vector<poss>, cmp> r;
int main()
{
    //tb;
    poss s, next;
    while(cin>>n>>m>>t){
        ll flag = 0, findt = 0;
        memset(smap, 0, sizeof(smap));
        while(!r.empty())r.pop();
        //输入地图
        for(ll i = 1; i <= n; i++)cin>>map[i];
        //处理传送门
        while(t--){
            cin>>a1>>a2>>b1>>b2;
            a1 += 1; a2 += 1; b1 += 1; b2 += 1;
            if(map[a1][a2] == '#'||map[b1][b2] == '#')continue;
            s.x  = a1; s.y  = a2;
            s.xj = b1; s.yj = b2; s.step = 1e9;
            smap[a1][a2] = -1;
            r.push(s);
        }
        //寻找起点并进入队列
        for(ll i = 1; i <= n; i++)
        for(ll j = 1; j <= m; j++)
            if(map[i][j] == 'S'){s.x = i; s.y = j; s.step = 0; r.push(s);}
        //bfs大法
        while(!r.empty()){
            if(findt) break;
            s = r.top();
            //四个方向拓展
            for(ll i = 0; i < 4; i++){
                next.x = s.x + dir[i][0];
                next.y = s.y + dir[i][1];
                //找到就返回
                if(map[next.x][next.y] == 'T'){
                    cout<<s.step + 1<<'\n';
                    flag = 1; findt = 1; break;
                }
                //有传送门且开启(就是将出口入队)
                if(smap[next.x][next.y] == -1){
                    next.x = s.xj; next.y = s.yj; next.step = s.step + 3;
                    if(!smap[next.x][next.y] || smap[next.x][next.y] > next.step)
                        r.push(next), smap[next.x][next.y] = next.step;
                }
                //没有传送门或者有传送门但没开启
                next.step = s.step + 1;
                if(!smap[next.x][next.y] || smap[next.x][next.y] > next.step)
                if(next.x > 0 && next.x <= n && next.y > 0 && next.y <=m && map[next.x][next.y] != '#')
                    r.push(next), smap[next.x][next.y] = next.step;
            }
            r.pop();
        }
        if(!flag)cout<<"-1\n";
    }
    return 0;
}
题解专栏 文章被收录于专栏

希望不断进步

全部评论

相关推荐

10-19 10:28
已编辑
西南石油大学 后端工程师
团孝子已上线feeling:面了很多家公司,能感受到目前只有小公司+外包喜欢问八股。大厂虽然也问八股,但是是从实习、项目中进行提问,并且大厂会问很深,面试官也会对你的回答进行思考➕追问,所以准备大厂面试前一定要备好相关资料。对于算法,我做的是codetop前100+力扣hot100+力扣高频150,面试中实感hot100就足够,基本上只要是hot100就秒答。对于项目和八股,我做的也是烂大街的星球项目,八股则是看小林和问ai,自己也写了很多技术博客和画了很多思维导图,并且自己也尝试用嘴巴说出来,不只停留于纸面。运气也很重要,必须要让面试官/HR看到简历才行,所以建议投递时间是下午两点。tl:第一岗位9.9&nbsp;投递9.10&nbsp;一面(一面评价:最近见过最强的大三,结束五分钟后约二面,都晚上九点了不下班吗)9.11&nbsp;二面(三道算法a出两道,反问评价:经验不够等横向,我实习生要啥经验)9.21挂(实习时间过短+其他原因,想要一年实习的,为什么不招个正职)第二岗位10.10投递10.11约面(主管打电话,说看到我之前投递记录了想要我挂qa职进去干后端,同意)10.14&nbsp;一面(无八股,主动说确实很强,意愿很强)10.16&nbsp;oc其余,友邦,东软,东华,惠择,用友oc已拒京东测开一面挂(投后端被测开捞)腾讯测试已拒(投后端被测开捞)ps:表扬惠择的主管面,没怎么问技术(可能是一面面试官沟通过了),全程一起讲大道理,解答了心中很多疑惑,也告诉我以面试官角度来看怎么选候选人,如果可以下次一定选惠择
HeaoDng:美团好像可以触发一面通
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务