Safe Path Gym - 101755H(题解)

原题

http://codeforces.com/gym/101755/problem/H

题目大意

题目是讲给一个图,然后这个图包含一个's'表示起点,' f'字符表示终点,如果起点能到达终点,输出最短路,否则输出-1.图的'.'字符是能到达的点,'M'字符是代表怪物的点,题目会给一个d,意思是这个怪物能最多能走d步(从'M'点算起),这些怪物能到达的点是不能走的.

题目分析

(阅读该题解可能需要先大概了解bfs的结构)这道题是最短路径问题,可以用bfs解决,不过要注意的地图有一些点是不能到达的,就是怪物能到达的点,因此在输入地图后应该先用一次bfs把怪物能到达的点全部标记一下(这里注意怪物有可能直接能到达起点或者终点,因此一遇到这种情况可以直接输出-1),再创建另一幅规格与地图相同的图,每一格的数字表示从起点到该点的距离(初始化为-1,-1表示无法到达),令该图起点为0,然后从起点开始bfs同时不断更新地图,当bfs扫完一遍地图后(或者扫到终点直接退出bfs),输出该图终点的数据即可.(具体细节在代码注释)(注意bfs if判定语句要写好)

代码

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <string>
  8 #include <utility>
  9 #include <queue>
 10 #include <stack>
 11 const int INF=0x3f3f3f3f;
 12 using namespace std;
 13 
 14 typedef pair<int,int> P;  
 15 vector<string> a; //用来存地图 
 16 vector< vector<int> > b; //用来存地图上各点距起点的最短距离 
 17 struct N
 18 {
 19     int x,y; 
 20     N(){}
 21     N(int _x,int _y){x=_x,y=_y;} //结构体构建函数 
 22 };
 23 queue<pair<N,int> > que0; //N用来存坐标, int用来存怪物走的步数 
 24 int n,m; //地图规模 
 25 int sx,sy,gx,gy; //地图起点和终点 
 26 int dx[]={1,-1,0,0},dy[]={0,0,1,-1}; //枚举前进方向 
 27 int s=1;  //s用来标记怪物能否到达起点和终点 
 28 
 29 void bfs1(int d) //用来标记地图 
 30 {
 31     while(que0.size())
 32     {
 33         pair<N,int> p=que0.front();
 34         que0.pop();
 35         if(p.second>=d) break; //怪物已经走到限定步数就可以直接结束 
 36         for(int i=0;i<4;i++)
 37         {
 38             int nx=p.first.x+dx[i],ny=p.first.y+dy[i];
 39             if(nx>=0&&nx<n&&ny>=0&&ny<m&&a[nx][ny]!='#')
 40             {
 41                 if(a[nx][ny]=='S'||a[nx][ny]=='F') {s=0;return ;} 
 42                 que0.push(make_pair(N(nx,ny),p.second+1));
 43                 a[nx][ny]='#';
 44             }
 45         }
 46     }
 47 }
 48 
 49 int bfs2() //用来刷新距离 
 50 {
 51     queue<P> que;
 52     for(int i=0;i<n;i++) //用来创建另一幅图 
 53     {
 54         b.push_back(vector<int>());
 55         for(int j=0;j<m;j++)
 56         b[i].push_back(-1);
 57     }
 58     que.push(P(sx,sy));
 59     b[sx][sy]=0; //起点距离为0 
 60     while(que.size())
 61     {
 62         P p=que.front();que.pop();
 63         if(p.first==gx&&p.second==gy) break; //扫到终点就可以终止该bfs了 
 64         for(int i=0;i<4;i++)
 65         {
 66             int nx=p.first+dx[i],ny=p.second+dy[i];
 67             if(nx>=0&&nx<n&&ny>=0&&ny<m&&a[nx][ny]!='#'&&b[nx][ny]==-1)
 68             {
 69                 que.push(P(nx,ny));
 70                 b[nx][ny]=b[p.first][p.second]+1;
 71             }
 72         }
 73     }
 74     return b[gx][gy];
 75 }
 76 
 77 int main()
 78 {
 79     int d;
 80     cin>>n>>m>>d;
 81     string temp;
 82     for(int i=0;i<n;i++) //读入地图 
 83     {
 84     cin>>temp;
 85     a.push_back(temp);
 86     }
 87     for(int i=0;i<n;i++)
 88     for(int j=0;j<m;j++)
 89     {
 90         if(a[i][j]=='M') a[i][j]='#',que0.push(make_pair(N(i,j),0)); //'#'是不能到达的方格 
 91         if(a[i][j]=='S') sx=i,sy=j;
 92         if(a[i][j]=='F') gx=i,gy=j;
 93     }
 94     bfs1(d);
 95     if(!s) cout<<-1<<endl;
 96     else
 97     {
 98         cout<<bfs2()<<endl;
 99     }
100     return 0;
101 }

 

转载于:https://www.cnblogs.com/VBEL/p/10427918.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值