我是靠谱客的博主 孝顺萝莉,这篇文章主要介绍UVA 816 Abbott's Revenge BFS求最短路+路径输出(详细注释),现在分享给大家,希望可以做个参考。

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=757

Sample Input
SAMPLE 3 1 N 3 3 1 1 WL NR * 1 2 WLF NR ER * 1 3 NL ER * 2 1 SL WR NF * 2 2 SL WF ELF * 2 3 SFR EL * 0 NOSOLUTION 3 1 N 3 2 1 1 WL NR * 1 2 NL ER * 2 1 SL WR NFR * 2 2 SR EL * 0 END
Sample Output
SAMPLE (3,1) (2,1) (1,1) (1,2) (2,2) (2,3) (1,3) (1,2) (1,1) (2,1) (2,2) (1,2) (1,3) (2,3) (3,3) NOSOLUTION No Solution Possible

题意:一个迷宫,根据来的方向不同可以往不同的方向走,求起点到终点的最短路,并输出路径。

题解:与普通迷宫本质相同,但需要再多一维表示当前朝向。坑点在于输入和输出,输入由于字符过多,用scanf极易出错,用cin就容易多了。输出的各种空格,小心谨慎。

AC代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; struct Node{ int r, c; //横纵坐标 int dir; //目前面朝方向 Node(int rr = 0, int cc = 0, int ddir = 0):r(rr), c(cc), dir(ddir){} }; const char* dirs = "NESW"; //目前面朝方向 const char* turns = "FLR"; //可以转向的方向 int dir_id(char c){return strchr(dirs, c) - dirs;} //将输入的方向转成数字 int turn_id(char c){return strchr(turns, c) - turns;} const int dr[] = {-1, 0, 1, 0}; //上, 右, 下, 左 const int dc[] = {0, 1, 0, -1}; int d[10][10][4]; //初始状态到(r, c, dir)最短路长度 Node p[10][10][4]; //(r, c, dir)在BFS树中的父结点 int r0, c0, r1, dir, c1, r2, c2; //r0, c0起点, r2, c2终点, c1, r1, dir当前状态 string name, s; char c; bool has_edge[10][10][4][3]; //点坐标在每个方向的三个转向是否访问 bool inside(int r, int c){ //判断是否越界 return (r >= 1 && r <= 9 && c >= 1 && c <= 9); } bool Input(){ cin >> name; //输入样例名 if(name == "END") return false; cout << name << endl; cin >> r0 >> c0 >> c >> r2 >> c2; //输入起点,目前朝向,终点(用scanf读入容易wa) dir = dir_id(c); r1 = r0 + dr[dir]; c1 = c0 + dc[dir]; //实际上以起点的下一个点为起点 memset(has_edge, false, sizeof(has_edge)); int a, b; while(cin >> a && a){ //读入每一个点,及其能到达的方向 cin >> b; while(cin >> s){ if(s[0] == '*') break; int tempd = dir_id(s[0]); //tempd保存当前朝向 for(int i = 1; i < s.size(); i++) has_edge[a][b][tempd][turn_id(s[i])] = true; } } return true; //当前样例输入完成,可正常进入solve函数 } Node walk(const Node& u, int turn){ int dir = u.dir; //不满足下列条件即为直行 if(turn == 1) dir = (dir + 3) % 4; //向左转 if(turn == 2) dir = (dir + 1) % 4; //向右转 return Node(u.r + dr[dir], u.c + dc[dir], dir); } void print_ans(Node u){ vector<Node> nodes; for(;;){ //从终点起, 先通过p数组,找到每个结点的父结点,放到vector中 nodes.push_back(u); if(d[u.r][u.c][u.dir] == 0) break; //找到起点, 结束循环 u = p[u.r][u.c][u.dir]; } nodes.push_back(Node(r0, c0, dir)); //最后将起点也放入vector中 int cnt = 0; for(int i = nodes.size() - 1; i >= 0; i--){ //逆序输出,注意空格 if(cnt % 10 == 0) cout << " "; cout << " (" << nodes[i].r << "," << nodes[i].c << ")"; if(++cnt % 10 == 0) cout << endl; } if(nodes.size() % 10 != 0) cout << endl; } void solve(){ //进入BFS树 queue<Node> q; memset(d, -1, sizeof(d)); Node u(r1, c1, dir); d[r1][c1][dir] = 0; q.push(u); while(!q.empty()){ Node u = q.front(); q.pop(); if(u.r == r2 && u.c == c2){ //找到终点,输出结果 print_ans(u); return; } for(int i = 0; i < 3; i++){ //分别超三个方向走,看能否走通 Node v = walk(u, i); if(has_edge[u.r][u.c][u.dir][i] && inside(v.r, v.c) && d[v.r][v.c][v.dir] < 0){ //通路,未出界, 未访问过 d[v.r][v.c][v.dir] = d[u.r][u.c][u.dir] + 1; p[v.r][v.c][v.dir] = u; //保存v 的父结点为 u q.push(v); } } } cout << " No Solution Possible" << endl; //此处注意No前有两个空格 } int main(){ while(Input()){ solve(); } return 0; }

最后

以上就是孝顺萝莉最近收集整理的关于UVA 816 Abbott's Revenge BFS求最短路+路径输出(详细注释)的全部内容,更多相关UVA内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(88)

评论列表共有 0 条评论

立即
投稿
返回
顶部