武汉工程大学第三届ACM程序设计选拔赛B题——密室逃脱(最短路)

链接:
武汉工程大学第三届ACM程序设计选拔赛B题
来源:牛客网
题面:
小明没有打过校赛但是他被拉去出题了。他非常想打校赛,但是他现在被困到了迷宫出题,现在请你帮小明逃离出题现场。该迷宫由n * m个格子组成的迷宫,有些格子是陷阱,用’#‘表示,小明进入陷阱就会死亡,’.'表示没有陷阱。小明所在的位置用’S’表示,目的地用’T’表示。
小明只能向上下左右相邻的格子移动,每移动一次花费1秒。
有q个双向传送阵,每个传送阵各有两个口,都在迷宫的格子里,当走到或被传送到一个有传送阵的格子时,小明可以选择是否开启传送阵。如果开启传送阵,小明就会被传送到传送阵的另一端的格子里,这个过程会花费3秒;如果不开启传送阵,将不会发生任何事情,小明可以继续向上下左右四个方向移动。
一个格子可能既有多个传送阵,小明可以选择任意一个开启传送阵。使用传送阵是非常危险的,因为有的传送阵的另一端在陷阱里,如果小明使用这样的传送阵,那他就会死亡。请告诉小明活着逃离出题现场的最短时间。

比赛的时候死活没想出来是最短路,一直以为是道搜索题,赛后看了题解才恍然大悟(害,太菜了),本题主要是将二维压缩为一维,然后用dijkstra或者bellmen-ford跑一遍,最后判断是否可到达.

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define speed(x) ios::sync_with_stdio(false),cin.tie(x),cout.tie(x)
#define debug(x) cout<<#x<<'='<<x<<'\n';
using namespace std;
#define P pair<int,int>
const int MAX_N = 303;
const int mod = 1e9+9;
int n,m,q;
int d[MAX_N*MAX_N];
int gx[]={0,0,1,-1};
int gy[]={1,-1,0,0};
struct node{int to,cost;};
string s[MAX_N];
vector<node>edge[MAX_N*MAX_N];
bool used[MAX_N*MAX_N];
inline int nn(int i,int j){ return m*(i-1)+j;}
bool operator<(const node &a,const node &b){ return a.cost>b.cost;}
void addedge(int i,int j){
    if(s[i-1][j-1]=='#') return;
    for(int k=0;k<4;k++){
        int nx=i+gx[k],ny=j+gy[k];
        if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&s[nx-1][ny-1]!='#'){
            int u=nn(i,j),v=nn(nx,ny);
            edge[u].emplace_back(node{v,1});
            edge[v].emplace_back(node{u,1});
        }
    }
}
int main(){
    speed(nullptr);
    cin>>n>>m>>q;
    int S=0,T=0;
    for(int i=0;i<n;i++){
        cin>>s[i];
        for(int j=0;j<s[i].size();j++){
            if(s[i][j]=='S') S=nn(i+1,j+1);
            if(s[i][j]=='T') T=nn(i+1,j+1);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            addedge(i,j);
            d[nn(i,j)]=INF;
        }
    }
    while(q-->0){
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        if(s[x1][y1]=='#'||s[x2][y2]=='#') continue;
        edge[nn(x1+1,y1+1)].emplace_back(node{nn(x2+1,y2+1),3});
        edge[nn(x2+1,y2+1)].emplace_back(node{nn(x1+1,y1+1),3});
    }
    priority_queue<node>q;
    d[S]=0;
    q.emplace(node{S,d[S]});
    while(!q.empty()){
        node e=q.top();
        q.pop();
        if(used[e.to]) continue;
        used[e.to]=true;
        for(auto [x,y]:edge[e.to]){
            if(!used[x]&&d[x]>d[e.to]+y){
                d[x]=d[e.to]+y;
                q.emplace(node{x,d[x]});
            }
        }
    }
    cout<<(d[T]==INF?-1:d[T])<<'\n';
    return 0;
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值