献给阿尔吉农的花❀
题目描述:
阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫。
今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔吉侬最喜欢的奶酪。
现在研究员们想知道,如果阿尔吉侬足够聪明,它最少需要多少时间就能吃到奶酪。
迷宫用一个 R×CR×C 的字符矩阵来表示。
字符 S 表示阿尔吉侬所在的位置,字符 E 表示奶酪所在的位置,字符 # 表示墙壁,字符 . 表示可以通行。
阿尔吉侬在 1 个单位时间内可以从当前的位置走到它上下左右四个方向上的任意一个位置,但不能走出地图边界。
输入格式
第一行是一个正整数 TT,表示一共有 TT 组数据。
每一组数据的第一行包含了两个用空格分开的正整数 RR 和 CC,表示地图是一个 R×CR×C 的矩阵。
接下来的 RR 行描述了地图的具体内容,每一行包含了 CC 个字符。字符含义如题目描述中所述。保证有且仅有一个 S 和 E。
输出格式
对于每一组数据,输出阿尔吉侬吃到奶酪的最少单位时间。
若阿尔吉侬无法吃到奶酪,则输出“oop!”(只输出引号里面的内容,不输出引号)。
每组数据的输出结果占一行。
数据范围
1<T≤101<T≤10,
2≤R,C≤2002≤R,C≤200
输入样例:
3
3 4
.S..
###.
..E.
3 4
.S..
.E..
....
3 4
.S..
####
..E.
输出样例:
5 1 oop!
BFS 先把初始状态入队,然后进入循环,1.弹出队头 2.拓展队头的子节点( 判个重) ,然后压入队尾
23 /**
24 * 思路做法: 25 * 26 * 1. 起点入队, 27 * 28 * 若队列非空则 执行{ 29 30 1.队头取值,并出队 31 扩展t 的新结点 bfs 宽搜 32 for(扩展t) { ver 新点, if(!st[t]) 没出现过 则入队尾 } 33 34 } 35 * 36 * 37 38 */
make_pair():
```
make_pair的用法
无需写出型别, 就可以生成一个pair对象
例:std::make_pair(42, '@');
而不必费力写成:std::pair<int, char>(42, '@')
当有必要对一个接受pair参数的函数传递两个值时, make_pair()尤其显得方便,void f(std::pair<int, const char*>);
void foo{
f(std::make_pair(42, '@')); //pass two values as pair
}
```
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 5 #include <queue> 6 7 using namespace std; 8 const int N= 210; 9 10 typedef pair<int ,int> PII; 11 #define x first 12 #define y second 13 14 char g[N][N]; 15 // 存储图 16 17 int dist[N][N]; 18 // 存储 到每个点的距离 路径长度 19 // 判重数组,遍历过走到过,则不再走, dist数组当作距离数组和判重数组 20 21 int n, m; // 行列 22 23 /** 24 * 思路做法: 25 * 26 * 1. 起点入队, 27 * 28 * 若队列非空则 执行{ 29 30 1.队头取值,并出队 31 扩展t 的新结点 bfs 宽搜 32 for(扩展t) { ver 新点, if(!st[t]) 没出现过 则入队尾 } 33 34 } 35 * 36 * 37 38 */ 39 40 int dx[] = {-1,0,1,0}, dy[] = {0,1,0,-1}; // 上右下左 41 42 43 // 44 int bfs(PII start, PII end) 45 { 46 queue<PII> q; // 队列 47 memset(dist, -1 , sizeof dist); // 距离初始化为-1 , dist[a][b] == -1 说明没有走到过 48 49 dist[start.x][start.y] = 0; // 起点 距离为0; 50 51 q.push(start); // 起点入队 52 53 while( q.size()) 54 { 55 PII t; 56 t = q.front(); // 队列的队头是 front(); 栈顶是top(); 57 //取出队头 58 q.pop(); 59 // 弹出队头 60 61 for(int i = 0; i<4; i++) // 扩展t的dx,dy 62 { 63 int a = t.x + dx[i], b = t.y + dy[i]; 64 65 if(a>=n || a<0 || b>=m || b <0) continue; 66 //出界跳出本次循环 67 68 if(dist[a][b] != -1) continue; 69 //遍历过了,跳过 70 71 if(g[a][b] == '#') continue; 72 // # 跳过 73 74 dist[a][b] = dist[t.x][t.y] + 1; 75 76 if(end == make_pair(a,b)) return dist[a][b]; // 走到了终点, 结束。 77 78 79 q.push({a,b}); 80 81 //没有出现过, 则入队尾 82 } 83 84 } 85 86 return -1; 87 } 88 89 int main(){ 90 int t; 91 cin >> t ; 92 93 while( t -- ) 94 { 95 cin >> n >> m; 96 97 for(int i = 0; i<n; i++) cin >> g[i]; 98 99 PII start, end; 100 101 for(int i = 0 ; i<n ; i++) 102 for(int j = 0 ; j <m; j++) 103 { 104 if(g[i][j] == 'S') start = {i,j}; 105 else if(g[i][j] == 'E') end = {i,j}; 106 } 107 108 int distance = bfs(start, end); // dfs 返回S 到E 最少走的次数 109 110 111 112 if(distance == -1) cout << "oop!" << endl; 113 else cout << distance << endl; 114 115 } 116 117 118 119 120 121 122 return 0; 123 }
bfs():
// queue<PII> q; // 队列
// memset(dist, -1 , sizeof dist); // 距离初始化为-1 , dist[a][b] == -1 说明没有走到过
// dist[start.x][start.y] = 0; // 起点 距离为0;
// q.push(start); // 起点入队
// 队列不空: while( q.size())
// 队列的队头是 front(); 栈顶是top();
//取出队头
// 弹出队头
// for(int i = 0; i<4; i++) // 扩展t的dx,dy
//出界跳出本次循环 //遍历过了,跳过 // # 跳过
// 这个点的距离= 上各点的距离+1 , 每次前进一个位置, 则加1, 刚好就是走的距离
// 走到了终点, 结束。
//没有出现过, 则入队尾