仙岛求药

    科技2022-07-11  126

    问题描述

    少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶。叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处。迷阵由M×N个方格组成,有的方格内有可以瞬秒李逍遥的怪物,而有的方格内则是安全。现在李逍遥想尽快找到仙药,显然他应避开有怪物的方格,并经过最少的方格,而且那里会有神秘人物等待着他。现在要求你来帮助他实现这个目标。

    输入

    输入有多组测试数据. 每组测试数据以两个非零整数 M 和 N 开始,两者均不大于20。M 表示迷阵行数, N 表示迷阵列数。接下来有 M 行, 每行包含N个字符,不同字符分别代表不同含义: 1) ‘@’:少年李逍遥所在的位置; 2) ‘.’:可以安全通行的方格; 3) ‘#’:有怪物的方格; 4) ‘*’:仙药所在位置。 当在一行中读入的是两个零时,表示输入结束。

    输出

    对于每组测试数据,分别输出一行,该行包含李逍遥找到仙药需要穿过的最少的方格数目(计数包括初始位置的方块)。如果他不可能找到仙药, 则输出 -1。

     

    样例

    INPUT

    8 8

    .@##...# #....#.# #.#.##.. ..#.###. #.#...#. ..###.#.

    OUTPUT

    10

    解题思路

    BFS。

    求最短路径且有地图,优先使用BFS。为了每次用队列能完整地存储每个点的信息(坐标x,y和步数sum),创建一个结构体

    struct road{ int x;//横坐标 int y;//纵坐标 int sum;//已走的步数 };

     

    为清楚地描述行进的方向,创建一个二维数组

    int dir[4][2] = { {1, 0},{-1, 0},{0, 1},{0, -1} };//向右、向左、向上、向下(在后面遍历的时候加上相应的数字)

    创建队列后,先放入初始信息即起点的x,y,sum=0;之后不断进行四个方位的扫描,如果满足行进条件(本题中是不越界且!=‘#’),则对此处进行标记(标记过的地方就不必再走了)。

    如果找到了仙药,则返回sum+1;如果没找到,则让刚刚查询的这个点入队,sum++,循环往复。

     

    完整代码

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <iomanip> #include <queue> using namespace std; int flag[21][21]; char s[21][21]; int n, m; int MapBeginX, MapBeginY, MapEndX, MapEndY;//用于保存起点和终点位置 struct road{ int x; int y; int sum; }; queue<road> Q; int dir[4][2] = { {1, 0},{-1, 0},{0, 1},{0, -1} }; int bfs(int be, int en){//参数为起点和终点 flag[be][en] = 1;//标记起点 road rr; rr.x = be; rr.y = en; rr.sum = 0; Q.push(rr);//存储起点信息 while(!Q.empty()){ road r = Q.front(); Q.pop(); for(int i = 0; i < 4; i++){//开始四处遍历 int temx = r.x + dir[i][0]; int temy = r.y + dir[i][1]; if(temx >= 0&&temx <n&&temy >= 0&&temy <m&&(!flag[temx][temy])&&(s[temx][temy] == '.')){//满足条件 flag[temx][temy] = 1;//标记 if(temx == MapEndX&&temy == MapEndY){//找到 return r.sum + 1; } //未找到 road rrr; rrr.x = temx; rrr.y = temy; rrr.sum = r.sum + 1; Q.push(rrr); } } } return 0; } int main(){ cin>>n>>m; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ cin>>s[i][j]; } } for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ if(s[i][j] == '@'){//保存起点终点坐标 MapBeginX = i; MapBeginY = j; }else if(s[i][j] == '*'){ MapEndX = i; MapEndY = j; s[i][j] = '.';//保存过后置'.'保证搜索到终点时满足条件 } } } int X = bfs(MapBeginX, MapBeginY); if(X) cout<<X<<endl; else cout<<"-1"<<endl;//达不到时返回-1 return 0; }

     

    Processed: 0.010, SQL: 8