ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

1018 maze 优先队列+bfs

2022-07-01 23:34:22  阅读:237  来源: 互联网

标签:小明 传送 .. int bfs ..... 1018 maze define


链接:https://ac.nowcoder.com/acm/contest/23156/1018
来源:牛客网

题目描述

小明来到一个由n x m个格子组成的迷宫,有些格子是陷阱,用'#'表示,小明进入陷阱就会死亡,'.'表示没有陷阱。小明所在的位置用'S'表示,目的地用'T'表示。
小明只能向上下左右相邻的格子移动,每移动一次花费1秒。
有q个单向传送阵,每个传送阵各有一个入口和一个出口,入口和出口都在迷宫的格子里,当走到或被传送到一个有传送阵入口的格子时,小明可以选择是否开启传送阵。如果开启传送阵,小明就会被传送到出口对应的格子里,这个过程会花费3秒;如果不开启传送阵,将不会发生任何事情,小明可以继续向上下左右四个方向移动。
一个格子可能既有多个入口,又有多个出口,小明可以选择任意一个入口开启传送阵。使用传送阵是非常危险的,因为有的传送阵的出口在陷阱里,如果小明使用这样的传送阵,那他就会死亡。也有一些传送阵的入口在陷阱里,这样的传送阵是没有用的,因为小明不能活着进入。请告诉小明活着到达目的地的最短时间。

输入描述:

有多组数据。对于每组数据:
第一行有三个整数n,m,q(2≤ n,m≤300,0≤ q ≤ 1000)。
接下来是一个n行m列的矩阵,表示迷宫。
最后q行,每行四个整数x
1
,y
1
,x
2
,y
2
(0≤ x
1
,x
2
< n,0≤ y
1
,y
2
< m),表示一个传送阵的入口在x
1
行y
1
列,出口在x
2
行y
2
列。

输出描述:

如果小明能够活着到达目的地,则输出最短时间,否则输出-1。
示例1

输入

复制
5 5 1
..S..
.....
.###.
.....
..T..
1 2 3 3
5 5 1
..S..
.....
.###.
.....
..T..
3 3 1 2
5 5 1
S.#..
..#..
###..
.....
....T
0 1 0 2
4 4 2
S#.T
.#.#
.#.#
.#.#
0 0 0 3
2 0 2 2

输出

复制
6
8
-1
3

备注:

坐标从0开始

分析

bfs + 优先队列

1.//一开始感觉直接一个简单bfs就好了
2.//后来发现原来一个位置有多个传送阵。。就不知道该用什么数据结构存储了,而且不知道距离最短该怎么表示,那个时候在我印象里,bfs还是一个一个相邻的点向外扩展

3.然后看了雨巨的课,才知道bfs 一开始并不一定是用队列存储,队列只是保证了 bfs 向最近的点扩展的特性,而且bfs 有找最短路的特性,我们只需要用优先队列存储下一个可以到达的步数最短的点

就可以找到起点到终点的最短路径

4.但是还是不太会用优先队列写,属于是队列写习惯了,看了题解才知道,可以用大根堆,然后再结构体里面写一个单调递减,属于是负负得正得到一个存储 最小步数 的优先队列

5.不过题解里还是又不一样的地方,比如判断是在加入队列之后才判断,确实这样写代码少一点,因为有两种入队操作,一个传送阵,一个上下左右,但是时间复杂度也确实会多一点

6.然后抄了一遍,自己又写了一遍,就是a不了,后来发现,第一个t.step 写成 t.x,第二个<m 写成 < n,第三个忘记把优先队列清空

7.ac

 

#include<bits/stdc++.h>
#define TLE ios::sync_with_stdio(0),cin.tie(0)
#define endl "\n"
#define pb push_back
#define gg exit(0);
#define bd cout<<"debug"<<endl;
#define x first
#define None cout<<-1<<endl;
#define y second
#define all(a) a.begin(),a.end()
#define alll(a) a.begin()+1,a.end()
#define db(x) cout<<#x<<':'<<x<<endl;
#define dbb(i,a,b) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<#b<<':'<<b<<endl;
#define rt return;
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define V vector
#define fo(i,j,n) for(int i = j;i<=n;i++)
#define of(i,n,j) for(int i = n;i>=j;i--)
#define ent cout<<endl;
#define lowbit(x) (x&-x)
#define gcd(a,b) __gcd(a,b)
#define DEBUG 11243
using namespace std;
void clapping() {
     #if DEBUG == 1
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    #endif
}
typedef pair<int,int> PII;
typedef long long LL;
int dx[] = {0,1,0,-1,1,-1,1,-1,0};
int dy[] = {1,0,-1,0,1,-1,-1,1,0};

/*文档区


*/

//-------------------------代码----------------------------

//#define int LL

//一开始感觉直接一个简单bfs就好了
//后来发现原来一个位置有多个传送阵。。
//

const int N = 310;

PII st,ed;
struct Q {
    int x,y,step;
    bool operator<(const Q & s) const {
        return step > s.step;
    }
} ;
char mp[N][N];
bool vis[N][N];
V<PII> v[N][N];
int n,m,t;
priority_queue<Q> q;//大根堆,所以内部要把大的放到前面,才能变成小的在其那面

int bfs() {
    while(q.size()) {
        auto t = q.top();q.pop();//把大于m写成大于n了
        if(t.x < 1 || t.y < 1 || t.x > n || t.y > m || vis[t.x][t.y] || mp[t.x][t.y] == '#') continue;
        if(t.x == ed.x && t.y == ed.y) return t.step;
        vis[t.x][t.y] = true;
        fo(i,0,3) q.push({t.x + dx[i],t.y + dy[i],t.step + 1});
        for(auto u:v[t.x][t.y]) q.push({u.x,u.y,t.step + 3});//在这个不小心写成t.x了
    } return -1;
}

void solve() {
    while(cin>>n>>m>>t) {
        while(q.size())q.pop();//少了这个
        fo(i,1,n) {
            fo(j,1,m) {
                cin>>mp[i][j];
                if(mp[i][j] == 'S') st = {i,j};
                if(mp[i][j] == 'T') ed = {i,j};
                v[i][j].clear();
                vis[i][j] = 0;
            }
        } q.push({st.x,st.y,0});
        fo(i,1,t) {
            int a,b,c,d;cin>>a>>b>>c>>d;
            a ++ ,b ++ ,c ++ ,d ++ ;
            v[a][b].pb({c,d});
        }
        cout<<bfs()<<endl;
    }
}

signed main(){
    clapping();TLE;
    
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

标签:小明,传送,..,int,bfs,.....,1018,maze,define
来源: https://www.cnblogs.com/er007/p/16436241.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有