maze(优先队列写广搜)

链接:https://ac.nowcoder.com/acm/problem/15665
来源:牛客网

题目描述
小明来到一个由n x m个格子组成的迷宫,有些格子是陷阱,用’#‘表示,小明进入陷阱就会死亡,’.'表示没有陷阱。小明所在的位置用’S’表示,目的地用’T’表示。

小明只能向上下左右相邻的格子移动,每移动一次花费1秒。

有q个单向传送阵,每个传送阵各有一个入口和一个出口,入口和出口都在迷宫的格子里,当走到或被传送到一个有传送阵入口的格子时,小明可以选择是否开启传送阵。如果开启传送阵,小明就会被传送到出口对应的格子里,这个过程会花费3秒;如果不开启传送阵,将不会发生任何事情,小明可以继续向上下左右四个方向移动。

一个格子可能既有多个入口,又有多个出口,小明可以选择任意一个入口开启传送阵。使用传送阵是非常危险的,因为有的传送阵的出口在陷阱里,如果小明使用这样的传送阵,那他就会死亡。也有一些传送阵的入口在陷阱里,这样的传送阵是没有用的,因为小明不能活着进入。请告诉小明活着到达目的地的最短时间。
输入描述:
有多组数据。对于每组数据:
第一行有三个整数n,m,q(2≤ n,m≤300,0≤ q ≤ 1000)。
接下来是一个n行m列的矩阵,表示迷宫。
最后q行,每行四个整数x1,y1,x2,y2(0≤ x1,x2< n,0≤ y1,y2< m),表示一个传送阵的入口在x1行y1列,出口在x2行y2列。
输出描述:
如果小明能够活着到达目的地,则输出最短时间,否则输出-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

代码1:内存超限,这道题真的很卡内存的,我写了一个规规矩矩的bfs,结果上来就给我MLE。

#include <bits/stdc++.h>
#include <cstdio>
//#define local
using namespace std;
 
typedef unsigned long long ull;
typedef long long ll;
const int N =305;
const int inf = 0x3f3f3f3f;
 
int n,m,q,e,s;
int a[N][N],dis[N][N];
int dx[]= {1,-1,0,0},dy[]= {0,0,1,-1};
vector< pair<int,int> > pr[N][N];
 
void bfs()
{
    queue<int> q;
    while(!q.empty())
        q.pop();
    q.push(s);
    dis[s/m][s%m]=0;
    while(!q.empty())
    {
        int head=q.front();
        q.pop();
        for(int i=0; i<4; i++)
        {
            int u=head/m+dx[i],v=head%m+dy[i];
            if(u<0||u>=n||v<0||v>=m||!a[u][v])
                continue;
            if(dis[u][v]<dis[head/m][head%m]+1)
                continue;
            q.push(u*m+v);
            dis[u][v]=dis[head/m][head%m]+1;
        }
        for(int i=0; i<pr[head/m][head%m].size(); i++)
        {
            int x=pr[head/m][head%m][i].first;
            int y=pr[head/m][head%m][i].second;
            if(x<0||x>=n||y<0||y>=m||!a[x][y])
                continue;
            if(dis[x][y]<dis[head/m][head%m]+3)
                continue;
            q.push(x*m+y);
            dis[x][y]=dis[head/m][head%m]+3;
 
        }
    }
    printf("%d\n",dis[e/m][e%m]==inf?-1:dis[e/m][e%m]);
}
int main()
{
#ifdef local
    freopen("input.txt","r",stdin);
#endif // local
    while(scanf("%d%d%d",&n,&m,&q)!=EOF)
    {
        memset(dis,inf,sizeof(dis));
        memset(a,0,sizeof(a));
        for(int i=0; i<N; i++)
        {
            for(int j=0; j<N; j++)
                pr[i][j].clear();
        }
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                char c;
                scanf(" %c",&c);
                if(c=='S')
                {
                    s=i*m+j;
                    a[i][j]=1;
                }
                if(c=='T')
                {
                    e=i*m+j;
                    a[i][j]=1;
                }
                if(c=='#')
                    a[i][j]=0;
                if(c=='.')
                    a[i][j]=1;
            }
        }
        while(q--)
        {
            int x1,y1,x2,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            pr[x1][y1].push_back(make_pair(x2,y2));
        }
        bfs();
    }
    return 0;
}

代码2:看了大佬的代码,学会使用优先队列来维护求最短时间。

#include <bits/stdc++.h>
#include <cstdio>
#define local
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
const int N =305;
const int inf = 0x3f3f3f3f;

int n,m,q,ex,ey,sx,sy;
int a[N][N],vis[N][N];
int dx[]= {1,-1,0,0},dy[]= {0,0,1,-1};
vector< pair<int,int> > pr[N][N];
struct node
{
    int x,y,t;
    bool operator <(const node &b) const
    {
        return b.t<t;
    }
};
void bfs()
{
    priority_queue<node> qu;
    while(!qu.empty())
        qu.pop();
    qu.push({sx,sy,0});
    for(int i=0; i<pr[sx][sy].size(); i++)
    {
        int tx=pr[sx][sy][i].first,ty=pr[sx][sy][i].second;
        if(tx<0||tx>=n||ty<0||ty>=m||vis[tx][ty]||!a[tx][ty])
            continue;
        qu.push({tx,ty,3});
    }
    while(!qu.empty())
    {
        node head=qu.top();
        qu.pop();
        if(vis[head.x][head.y])
            continue;
        vis[head.x][head.y]=1;
        if(head.x==ex&&head.y==ey)
        {
            printf("%d\n",head.t);
            return ;
        }
        for(int j=0; j<4; j++)
        {
            int xx=head.x+dx[j],yy=head.y+dy[j];
            if(xx<0||xx>=n||yy<0||yy>=m||vis[xx][yy]||!a[xx][yy])
                continue;
            for(int i=0; i<pr[xx][yy].size(); i++)
            {
                int tx=pr[xx][yy][i].first,ty=pr[xx][yy][i].second;
                if(tx<0||tx>=n||ty<0||ty>=m||vis[tx][ty]||!a[tx][ty])
                    continue;
                qu.push({tx,ty,head.t+4});
            }
            qu.push({xx,yy,head.t+1});
        }
    }
    printf("-1\n");
}
int main()
{
#ifdef local
    freopen("input.txt","r",stdin);
#endif // local
    while(scanf("%d%d%d",&n,&m,&q)!=EOF)
    {
        memset(vis,0,sizeof(vis));
        memset(a,0,sizeof(a));
        for(int i=0; i<N; i++)
        {
            for(int j=0; j<N; j++)
                pr[i][j].clear();
        }
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                char c;
                scanf(" %c",&c);
                if(c=='S'){sx=i,sy=j;a[i][j]=1;}
                if(c=='T'){ex=i,ey=j;a[i][j]=1;}
                if(c=='#') a[i][j]=0;
                if(c=='.') a[i][j]=1;
            }
        }
        while(q--)
        {
            int x1,y1,x2,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            pr[x1][y1].push_back(make_pair(x2,y2));
        }
        bfs();
    }
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值