UVA-816.Abbott's Tevenge (BFS + 打印路径)
本题大意:给定一个迷宫,让你判断是否能从给定的起点到达给定的终点,这里起点需要输入起始方向,迷宫的每个顶点也都有行走限制,每个顶点都有特殊的转向约束...具体看题目便知...
本题思路:保存起点和终点的状态,保存每个顶点的状态,包括每个方向的可转向方向,然后直接BFS即可,记得保存每个儿子结点的爹,便于回溯输出路径。
参考代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct Node{ 5 int r, c, dir;// 表示结点的横纵坐标和方向 6 Node(int r = 0, int c = 0, int dir = 0) :r(r), c(c), dir(dir) {};//对结构体元素进行初始化 7 }; 8 const int maxn = 10; 9 const char *dirs = "NESW"; 10 const char *turns = "FLR"; 11 const int dr[] = {-1, 0, 1, 0}; 12 const int dc[] = {0, 1, 0, -1}; 13 int has_edge[maxn][maxn][4][3];//保存(r, c, dir)状态下的可移动方向 14 int d[maxn][maxn][4];//存储初始状态到(r, c, dir)的最短路长度 15 Node p[maxn][maxn][4];//同时用p[r][c][dir]保存了状态(r, c, dir)在BFS树中的父节点 16 int r0, c0, dir, r1, c1, r2, c2; 17 char name[99]; 18 19 int dir_id(char c) { 20 return strchr(dirs, c) - dirs; 21 } 22 23 int turn_id(char c) { 24 return strchr(turns, c) - turns; 25 } 26 27 Node walk(const Node &u, int turn) { 28 int dir = u.dir; 29 if(turn == 1) dir = (dir + 3) % 4;//逆时针 30 if(turn == 2) dir = (dir + 1) % 4;//顺时针 31 return Node(u.r + dr[dir], u.c + dc[dir], dir); 32 } 33 34 bool inside(int r, int c) { 35 return r >= 1 && r <= 9 && c >= 1 && c <=9; 36 } 37 38 bool read_case () { 39 char s[99], s2[99]; 40 scanf("%s", name); 41 if(!strcmp(name, "END")) return false; 42 scanf("%d %d %s %d %d", &r0, &c0, s2, &r2, &c2); 43 cout << name << endl; 44 dir = dir_id(s2[0]); 45 r1 = r0 + dr[dir]; 46 c1 = c0 + dc[dir]; 47 memset(has_edge, 0, sizeof(has_edge)); 48 while(true) { 49 int r, c; 50 scanf("%d", &r); 51 if(r == 0) break; 52 scanf("%d", &c); 53 while(~scanf("%s", s) && s[0] != '*') { 54 for(int i = 1; i < strlen(s); i ++) 55 has_edge[r][c][dir_id(s[0])][turn_id(s[i])] = 1; 56 } 57 } 58 return true; 59 } 60 61 void print_ans(Node u) { 62 //从目标节点逆序回溯到初始结点 63 vector <Node> nodes; 64 while(true) { 65 nodes.push_back(u); 66 if(d[u.r][u.c][u.dir] == 0) break; 67 u = p[u.r][u.c][u.dir]; 68 } 69 nodes.push_back(Node(r0, c0, dir)); 70 //打印解,每行10个 71 int cnt = 0; 72 for(int i = nodes.size() - 1; i >= 0; i --) { 73 if(cnt % 10 == 0) printf(" "); 74 printf(" (%d,%d)", nodes[i].r, nodes[i].c); 75 if(++ cnt % 10 == 0) printf("\n"); 76 } 77 if(nodes.size() % 10 != 0) printf("\n"); 78 } 79 80 void solve () { 81 queue <Node> q; 82 memset(d, -1, sizeof(d)); 83 Node u(r1, c1, dir); 84 d[u.r][u.c][u.dir] = 0; 85 q.push(u); 86 while(!q.empty()) { 87 Node u = q.front(); 88 q.pop(); 89 if(u.r == r2 && u.c == c2) { 90 print_ans(u); 91 return; 92 } 93 for(int i = 0; i < 3; i ++) { 94 Node v = walk(u, i); 95 if(has_edge[u.r][u.c][u.dir][i] && inside(v.r, v.c) && d[v.r][v.c][v.dir] < 0) { 96 d[v.r][v.c][v.dir] = d[u.r][u.c][u.dir] + 1; 97 p[v.r][v.c][v.dir] = u; 98 q.push(v); 99 } 100 } 101 } 102 printf(" No Solution Possible\n"); 103 } 104 105 int main () { 106 while(read_case()) { 107 solve(); 108 } 109 return 0; 110 }
时间并不会因为你的迷茫和迟疑而停留,就在你看这篇文章的同时,不知道有多少人在冥思苦想,在为算法废寝忘食,不知道有多少人在狂热地拍着代码,不知道又有多少提交一遍又一遍地刷新着OJ的status页面……
没有谁生来就是神牛,而千里之行,始于足下!