题目相关

题目链接

AtCoder Beginner Contest 184 E 题,https://atcoder.jp/contests/abc184/tasks/abc184_e。

Problem Statement

There is a town represented as a two-dimensional grid with H horizontal rows and W vertical columns.
A character ai,j describes the square at the i-th row from the top and j-th column from the left. Here, ai,j is one of the following: S , G , . , # , a, ..., and z.
# represents a square that cannot be entered, and a, ..., z represent squares with teleporters.

Takahashi is initially at the square represented as S. In each second, he will make one of the following moves:

  • Go to a non-# square that is horizontally or vertically adjacent to his current position.
  • Choose a square with the same character as that of his current position, and teleport to that square. He can only use this move when he is at a square represented as a, ..., or z.

Find the shortest time Takahashi needs to reach the square represented as G from the one represented as S.
If the destination is unreachable, report -1 instead.

Input

Input is given from Standard Input in the following format:

H W
a1,1 ... a1,w
.
.
.
ah,1 ... ah,w

Output

Print the shortest time Takahashi needs to reach the square represented as G from the one represented as S.
If the destination is unreachable from the initial position, print -1 instead.

Samples1

Sample Input 1

2 5
S.b.b
a.a.G

Sample Output 1

4

Explaination

Let (i,j) denote the square at the i-th row from the top and j-th column from the left.
Initially, Takahashi is at (1,1). One way to reach (2,5) in four seconds is:

  • go from (1,1) to (2,1);
  • teleport from (2,1) to (2,3), which is also an a square;
  • go from (2,3) to (2,4);
  • go from (2,4) to (2,5).

Samples2

Sample Input 2

11 11
S##...#c...
...#d.#.#..
..........#
.#....#...#
#.....bc...
#.##......#
.......c..#
..#........
a..........
d..#...a...
.#........G

Sample Output 2

14

Samples3

Sample Input 3

11 11
.#.#.e#a...
.b..##..#..
#....#.#..#
.#dd..#..#.
....#...#e.
c#.#a....#.
.....#..#.e
.#....#b.#.
.#...#..#..
......#c#G.
#..S...#...

Sample Output 3

-1

Constraints

  • 1≤H,W≤2000
  • ai,j is S, G, ., #, or a lowercase English letter. There is exactly one square represented as S and one square represented as G.

题解报告

题目翻译

有一个城镇可以用二维网格表示,该城镇水平方向有 H 行,垂直方向有 W 列。字符 描述最上边开始的第 i 行最左面开始的第 j 列,它的值是:S,G,.,#,a,...,z 其中一个。# 表示这个点不能进入,小写字母 a ~ z 表示传送点。

高桥开始的的位置为 S,他每次可以按照以下规则移动:

请找出高桥从 S 到 G 的最短路径,如果不存在,输出 -1。

题目分析

看完题目描述,走迷宫并且是找出最短路线,那么必然使用 BFS。本题和 BFS 模板相比,多了一个传送点,如何解决传送点问题。根据题目意思,我们一共有四种走法,即上、右、下、左。

我的思路是这样的:

1、在某个点判断下一个位置的时候,不考虑下一个点是否是传送点,和原有的 BFS 一样进行移动。

2、所有下一个可能位置计算完成后,判断这个点是否是传送点。如果是传送点,遍历修改传送点的代价 cost。修改结束,清空所有传送点。

下面我们使用样例数据来验证一下思路。

样例数据 1 分析

根据样例数据,起点在 (1,1) 位置。一般算法竞赛都将左上角定义为 1,1。起点的代价 cost 为 0,其余点的 cost 都为 INT_MAX。我们按照上、右、下、左进行遍历。首先将起点 (1,1) 加入到 BFS 的遍历队列中。下面我们开始模拟整个 BFS 遍历过程。

初始状态

cost 数组的值为

  1 2 3 4 5
1 0 INT_MAX INT_MAX INT_MAX INT_MAX
2 INT_MAX INT_MAX INT_MAX INT_MAX INT_MAX

第一轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (1,1),并删除该数据,我们从 (1,1) 开始遍历。目前的代价为 0,从这里出发到下一个位置的代价将为 2。

(1,1) 向上

新位置为 (1,0),走出了迷宫,不是合法位置。忽略。

(1,1) 向右

新位置为 (2,1),是合法位置,而且不是 #,可以走。当前 cost[2][1]=INT_MAX,更新 cost[2][1]=1,并吧 (2,1) 加入到 BFS 的遍历队列,此时 BFS 的遍历队列只有一个元素,即 (2,1)。

(1,1) 向下

新位置为 (1,2),是合法位置,而且不是 #,可以走。当前 cost[1][2]=INT_MAX,更新 cost[1][2]=1,并吧 (1,2) 加入到 BFS 的遍历队列,此时 BFS 的遍历队列只有两个元素,即 (2,1)、(1,2)。

(1,1) 向左

新位置为 (0,1),走出了迷宫,不是合法位置。忽略。

判断 (1,1) 是不是传送点

当前位置 (1,1) 不是传送点。

第一轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 INT_MAX INT_MAX INT_MAX
2 1 INT_MAX INT_MAX INT_MAX INT_MAX

第二轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (2,1),并删除该数据,我们从 (2,1) 开始遍历。目前的代价为 1,从这里出发到下一个位置的代价将为 2。

(2,1) 向上

新位置为 (2,0),走出了迷宫,不是合法位置。忽略。

(2,1) 向右

新位置为 (3,1),走出了迷宫,不是合法位置。忽略。

(2,1) 向下

新位置为 (2,2),是合法位置,而且不是 #,可以走。当前 cost[2][2]=INT_MAX,更新 cost[2][2]=2,并吧 (2,2) 加入到 BFS 的遍历队列,此时 BFS 的遍历队列只有三个元素,即 (1,2)、(2,2)。

(2,1) 向左

新位置为 (1,1),是合法位置,而且不是 #,可以走。当前 cost[1][1]=0,而我们移动的代价是 2,所以忽略。

判断 (2,1) 是不是传送点

当前位置 (2,1) 的值为 a,是传送点。遍历迷宫中所有值为 a 的传送点,可以传送的位置有 (2,3),将这个点的 cost 都改为 2,也就意味着 (1,1)->(3,2) 的代价是 2,同时将着两点加入到 BFS 队列中。此时 BFS 的遍历队列只有四个元素,即 (1,2)、(2,2)、(2,3)。同时我们清空所有 a 的传送点。

第二轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 INT_MAX INT_MAX INT_MAX
2 1 2 2 INT_MAX INT_MAX

第三轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (1,2),并删除该数据,我们从 (1,2) 开始遍历。目前已经的代价是 1,从这里出发到下一个位置的代价将为 2。

(1,2) 向上

新位置为 (1,1),是合法位置,而且不是 #,可以走。当前 cost[1][2]=0,而我们移动的代价是 2,就是从 (1,2) 移动到 (1,1) 的代价是 2。所以忽略。

(1,2) 向右

新位置为 (2,2),是合法位置,而且不是 #,可以走。新的路径代价没有缩小,忽略。说明我们不管是从 (1,1)->(2,1)->(2,2) 或者 (1,1)->(1,2)->(2,2) 的代价都是一样的。

(1,2) 向下

新位置为 (1,3),是合法位置,而且不是 #,可以走。当前 cost[1][3]=INT_MAX,更新 cost[1][3]=2,并吧 (1,3) 加入到 BFS 的遍历队列,此时 BFS 的遍历队列只有三个元素,即 (2,2)、(2,3)、(1,3)。

(1,2) 向左

新位置为 (0,2),走出了迷宫,不是合法位置。忽略。

判断 (1,2) 是不是传送点

当前位置不是传送点。

第三轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 2 INT_MAX INT_MAX
2 1 2 2 INT_MAX INT_MAX

第四轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (2,2),并删除该数据,我们从 (2,2) 开始遍历。目前已经的代价是 2,从这里出发到下一个位置的代价将为 3。

(2,2) 向上

新位置为 (2,1),是合法位置,而且不是 #,可以走。当前 cost[2][1]=1,而我们移动的代价是 3。所以忽略。

(2,2) 向右

新位置为 (3,2),走出了迷宫,不是合法位置。忽略。

(2,2) 向下

新位置为 (2,3),是合法位置,而且不是 #,可以走。当前 cost[2][3]=2,而我们移动的代价是 3。所以忽略。

(2,2) 向左

新位置为 (1,2),是合法位置,而且不是 #,可以走。当前 cost[1][2]=1,而我们移动的代价是 3。所以忽略。

判断 (2,2) 是不是传送点

当前位置不是传送点。

第四轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 2 INT_MAX INT_MAX
2 1 2 2 INT_MAX INT_MAX

第五轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (2,3),并删除该数据,我们从 (2,3) 开始遍历。目前已经的代价是 2,从这里出发到下一个位置的代价将为 3。

(2,3) 向上

新位置为 (2,2),是合法位置,而且不是 #,可以走。当前 cost[2][2]=2,而我们移动的代价是 3。所以忽略。

(2,3) 向右

新位置为 (3,3),走出了迷宫,不是合法位置。忽略。

(2,3) 向下

新位置为 (2,4),是合法位置,而且不是 #,可以走。当前 cost[2][4]=INT_MAX,更新 cost[2][4]=3,并吧 (2,4) 加入到 BFS 的遍历队列,此时 BFS 的遍历队列只有三个元素,即 (1,3)、(2,4)。

(2,3) 向左

新位置为 (1,3),是合法位置,而且不是 #,可以走。当前 cost[1][3]=2,而我们移动的代价是 3。所以忽略。

判断 (2,3) 是不是传送点

当前位置是传送点。但是这个传送点已经处理了,上面我们处理的时候,将这个队列清空。

第五轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 2 INT_MAX INT_MAX
2 1 2 2 3 INT_MAX

第六轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (1,3),并删除该数据,我们从 (1,3) 开始遍历。目前已经的代价是 2,从这里出发到下一个位置的代价将为 3。

(1,3) 向上

新位置为 (1,2),是合法位置,而且不是 #,可以走。当前 cost[1][2]=1,而我们移动的代价是 3。所以忽略。

(1,3) 向右

新位置为 (2,3),是合法位置,而且不是 #,可以走。当前 cost[2][3]=2,而我们移动的代价是 3。所以忽略。

(1,3) 向下

新位置为 (1,4),是合法位置,而且不是 #,可以走。当前 cost[1][4]=INT_MAX,更新 cost[1][4]=3,并吧 (2,4) 加入到 BFS 的遍历队列,此时 BFS 的遍历队列只有三个元素,即 (2,4)、(1,4)。

(1,3) 向左

新位置为 (0,3),走出了迷宫,不是合法位置。忽略。

判断 (1,3) 是不是传送点

当前位置是传送点 b。我们可以从这里传送到 (1,5)。当前 cost[1][5]=INT_MAX,更新 cost[1][5]=3,并吧 (1,5) 加入到 BFS 的遍历队列,此时 BFS 的遍历队列只有三个元素,即 (2,4)、(1,4)、(1,5)。清空传送点 b。

第六轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 2 3 3
2 1 2 2 3 INT_MAX

第七轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (2,4),并删除该数据,我们从 (2,4) 开始遍历。目前已经的代价是 3,从这里出发到下一个位置的代价将为 4。

(2,4) 向上

新位置为 (2,3),是合法位置,而且不是 #,可以走。当前 cost[2][3]=2,而我们移动的代价是 4。所以忽略。

(2,4) 向右

新位置为 (3,4),走出了迷宫,不是合法位置。忽略。

(2,4) 向下

新位置为 (2,5),是合法位置,而且不是 #,可以走。当前 cost[2][5]=INT_MAX,更新 cost[2][5]=4,并吧 (2,5) 加入到 BFS 的遍历队列,此时 BFS 的遍历队列只有三个元素,即 (1,4)、(1,5)、(2,5)。

(2,4) 向左

新位置为 (1,4),是合法位置,而且不是 #,可以走。当前 cost[1][4]=3,而我们移动的代价是 4。所以忽略。

判断 (2,4) 是不是传送点

当前位置不是传送点。

第七轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 2 3 3
2 1 2 2 3 4

第八轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (1,4),并删除该数据,我们从 (1,4) 开始遍历。目前已经的代价是 3,从这里出发到下一个位置的代价将为 4。

(1,4) 向上

新位置为 (1,3),是合法位置,而且不是 #,可以走。当前 cost[1][3]=2,而我们移动的代价是 4。所以忽略。

(1,4) 向右

新位置为 (2,4),是合法位置,而且不是 #,可以走。当前 cost[2][4]=3,而我们移动的代价是 4。所以忽略。

(1,4) 向下

新位置为 (1,5),是合法位置,而且不是 #,可以走。当前 cost[1][5]=4,而我们移动的代价是 4。所以忽略。

(1,4) 向左

新位置为 (0,4),走出了迷宫,不是合法位置。忽略。

判断 (1,4) 是不是传送点

当前位置不是传送点。

第八轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 2 3 3
2 1 2 2 3 4

第九轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (1,5),并删除该数据,我们从 (1,5) 开始遍历。目前已经的代价是 3,从这里出发到下一个位置的代价将为 4。

(1,5) 向上

新位置为 (1,4),是合法位置,而且不是 #,可以走。当前 cost[1][4]=3,而我们移动的代价是 4。所以忽略。

(1,5) 向右

新位置为 (2,5),是合法位置,而且不是 #,可以走。当前 cost[2][5]=4,而我们移动的代价是 4。所以忽略。

(1,5) 向下

新位置为 (1,6),走出了迷宫,不是合法位置。忽略。

(1,5) 向左

新位置为 (0,5),走出了迷宫,不是合法位置。忽略。

判断 (1,5) 是不是传送点

当前位置是传送点,但已经处理过。

第九轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 2 3 3
2 1 2 2 3 4

第十轮 BFS 遍历队列

BFS 遍历队列不为空,获取队首位置,得到 (2,5),并删除该数据,我们从 (2,5) 开始遍历。目前已经的代价是 4,从这里出发到下一个位置的代价将为 5。

(2,5) 向上

新位置为 (2,4),是合法位置,而且不是 #,可以走。当前 cost[2][4]=3,而我们移动的代价是 5。所以忽略。

(2,5) 向右

新位置为 (3,5),走出了迷宫,不是合法位置。忽略。

(2,5) 向下

新位置为 (2,6),走出了迷宫,不是合法位置。忽略。

(2,5) 向左

新位置为 (1,5),是合法位置,而且不是 #,可以走。当前 cost[1][5]=3,而我们移动的代价是 5。所以忽略。

判断 (2,5) 是不是传送点

当前位置是传送点,但已经处理过。

第十轮 BFS 遍历结束

cost 数组的值为

  1 2 3 4 5
1 0 1 2 3 3
2 1 2 2 3 4

到这里为止,BFS 队列为空,说明我们遍历了迷宫的所有点。遍历完成。

注意:只要 BFS 第一次走到终点,BFS 就可以停止了,因为 BFS 可以保证第一次就是最短路径。

AC 参考代码

//https://atcoder.jp/contests/abc184/tasks/abc184_e
//E - Third Avenue
#include <bits/stdc++.h>using namespace std;//如果提交到OJ,不要定义 __LOCAL
//#define __LOCALconst int MAXH=2e3+4;
const int MAXW=2e3+4;
char maze[MAXH][MAXW];
int cost[MAXH][MAXW];int h,w;
pair<int, int> qd;
pair<int, int> zd;
vector<pair<int, int>> tele[26];const int dx[]={0, 1, 0, -1};
const int dy[]={-1, 0, 1, 0};int bfs() {queue<pair<int, int>> q;q.push(qd);cost[qd.first][qd.second]=0;while (true!=q.empty()) {pair<int, int> cur = q.front();q.pop();int nc=cost[cur.first][cur.second]+1;//下一个位置的代价//新位置for (int i=0; i<4; i++) {int nx = cur.first+dx[i];int ny = cur.second+dy[i];//合法性判断if (nx<1||nx>h||ny<1||ny>w||'#'==maze[nx][ny]) {continue;}//路径判断if (nc<cost[nx][ny]) {cost[nx][ny]=nc;q.emplace(nx, ny);//判断是不是终点if (nx==zd.first && ny==zd.second) {return nc;}}}//如果是传送点if (maze[cur.first][cur.second]>='a' && maze[cur.first][cur.second]<='z') {//将所有的vector<pair<int, int>> &t=tele[maze[cur.first][cur.second]-'a'];vector<pair<int, int>>::iterator it;for (it=t.begin(); it!=t.end(); it++) {if (nc<cost[it->first][it->second]) {cost[it->first][it->second]=nc;q.emplace(it->first, it->second);}}t.clear();}}return -1;
}int main() {
#ifndef __LOCAL//这部分代码需要提交到OJ,本地调试不使用ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#endifcin>>h>>w;for (int i=1; i<=h; i++) {for (int j=1; j<=w; j++) {cost[i][j]=INT_MAX;cin>>maze[i][j];if ('S'==maze[i][j]) {//起点qd.first=i;qd.second=j;cost[i][j]=0;} else if ('G'==maze[i][j]) {zd.first=i;zd.second=j;} else if (maze[i][j]>='a' && maze[i][j]<='z') {tele[maze[i][j]-'a'].emplace_back(i, j);}}}//开始BFScout<<bfs()<<"\n";#ifdef __LOCAL//这部分代码不需要提交到OJ,本地调试使用system("pause");
#endifreturn 0;
}

时间复杂度

O(HW)。

空间复杂度

O(HW)。

AtCoder题解 —— AtCoder Beginner Contest 184 —— E - Third Avenue - BFS相关推荐

  1. AtCoder题解 —— AtCoder Beginner Contest 182 —— D - Wandering

    题目相关 题目链接 AtCoder Beginner Contest 182 D 题,https://atcoder.jp/contests/abc182/tasks/abc182_d. Proble ...

  2. AtCoder题解 —— AtCoder Beginner Contest 187 —— B - Gentle Pairs —— 暴力

    题目相关 题目链接 AtCoder Beginner Contest 187 B 题,https://atcoder.jp/contests/abc187/tasks/abc187_b. Proble ...

  3. AtCoder题解—— AtCoder Beginner Contest 181 —— B - Trapezoid Sum

    题目相关 题目链接 AtCoder Beginner Contest 181 B 题,https://atcoder.jp/contests/abc181/tasks/abc181_b. Proble ...

  4. AtCoder题解——AtCoder Grand Contest 048——A - atcoder < S

    题目相关 题目链接 AtCoder Grand Contest 048 A 题,https://atcoder.jp/contests/agc048/tasks/agc048_a. Problem S ...

  5. AtCoder题解 —— AtCoder Grand Contest 050 —— B - Three Coins —— 动态规划

    题目相关 题目链接 AtCoder Grand Contest 050 B 题,https://atcoder.jp/contests/agc050/tasks/agc050_b. Problem S ...

  6. AtCoder题解——AtCoder Regular Contest 107——B - Quadruple

    题目相关 题目链接 AtCoder Regular Contest 107 B 题,https://atcoder.jp/contests/arc107/tasks/arc107_b. Problem ...

  7. Atcoder题解与视频集

    开启Atcoder之路 开启Atcoder之路_sortmin的博客-CSDN博客_atcoder怎么用 atcoder心得 atcoder心得_404REN的博客-CSDN博客_atcoder怎么用 ...

  8. AtCoder题解——Beginner Contest 170——F - Pond Skater

    题目相关 题目链接 AtCoder Beginner Contest 170 F题,https://atcoder.jp/contests/abc170/tasks/abc170_f. Problem ...

  9. AtCoder题解——Beginner Contest 167——C - Skill Up

    题目相关 题目链接 AtCoder Beginner Contest 167 C题,https://atcoder.jp/contests/abc167/tasks/abc167_c. Problem ...

  10. AtCoder Beginner Contest 246 A~E 题解 Bishop 2

    AtCoder Beginner Contest 246 A~E 题解 A Four Points 题意 给你矩形的三个顶点,输出剩下那个 思路 把横坐标和纵坐标分开,必会存在两个相同的数,横纵坐标就 ...

最新文章

  1. 托管代码与非托管代码
  2. mysql 编译_mysql 5.7 编译——VS2017
  3. 【算法】快速选择算法 ( 数组中找第 K 大元素 )
  4. JSP+Servlet + JDBC 实现简单的登录验证模块
  5. SDN控制器OpenDaylight简介—VeCloud
  6. Java String关于replaceall函数转义字符的一个小贴士
  7. cmake (0)简介
  8. NOSQL 之 cassadra 安装与集群配置
  9. jzoj5702-[gdoi2018day2]滑稽子图【树形dp,二项式定理】
  10. Eclipse里的快捷键
  11. relativelayout中按键不能点_CNC | M80/M800系列系统常见按键和外部存储器故障
  12. 程序员职场:3 大原则让你的编程之路越走越顺,新手来了解一下
  13. leetcode 95 python
  14. 市面上有哪几种门_实木门、原木门、模压门,各有门道不怕坑!
  15. mysql自定义函数to_date_mysql 之 str_to_date ()函数 和date_format()函数
  16. python模块之subprocess
  17. C语言求解圆周率近似值
  18. Unity - Timeline 之 Timeline Preview and Timeline Selector(Timeline预览与Timeline选择器)
  19. win10无法msi文件的解决方法
  20. [转]伽利略卫星导航系统2019年7月14日起的宕机事件

热门文章

  1. 转:GRE_那些不讨人爱的4字母单词
  2. 联想 thinkpad usb 移动硬盘 u盘 BIOS 启动 ubuntu 系统
  3. android app闪退的原因分析,打开一个app就闪退解决方法
  4. 关于广告联盟的高价词问题
  5. 我是一个将近30岁的女程序员
  6. SIM800C AT指令编程
  7. 计算机专业群名有内涵,有内涵高大上的群名
  8. 【乐谱】摇篮曲(小宝宝要睡觉)五线谱-单音和声版
  9. HDOJ 5296 Annoying problem
  10. Vivado IP核之定点数转为浮点数Floating-point