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 }
View Code

 

posted @ 2019-03-15 22:31  Cruel_King  阅读(171)  评论(0编辑  收藏  举报