uva 816 Abbott的复仇
Posted 树的种子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uva 816 Abbott的复仇相关的知识,希望对你有一定的参考价值。
题目链接:https://uva.onlinejudge.org/external/8/816.pdf
紫书:P165
题意:
有一个最多包含9*9个交叉点的迷宫。输入起点、离开起点时的朝向和终点,求一条最短路(多解时任意输出一个即可)。
分析:
BFS的结点对状态转移的影响的因素有哪些,那么这个结点就要包含哪些信息。
左右,和东南西北的转换。
首先规定东南西北的顺时针。根据左右转向求出下一个方位。
下一个节点的坐标是有当前位置,和下一个状态的方向决定。
图的构建也是根据对结点状态转移的影响建图的。 has_edge[r][c][dir][turn] ,当前状态(r,c,dir)向 turn 方向走是否有路。
#include <bits/stdc++.h> using namespace std; struct Node { int r,c,dir; Node (int r=0,int c=0,int dir = 0) : r(r),c(c),dir(dir) {} }; const int Maxn = 10; const char* dirs = "NESW"; const char* turns = "FLR"; int dir_id(char c) { return strchr(dirs,c) - dirs; } int turn_id(int c) { return strchr(turns,c) - turns; } const int dr[] = {-1,0,1,0}; const int dc[] = {0,1,0,-1}; Node walk(const Node& u,int turn) { int dir = u.dir; if(turn==1) dir = (dir - 1 + 4)%4; ///向左转 if(turn==2) dir = (dir+ 1)%4; ///向右转 return Node(u.r+dr[dir],u.c+dc[dir],dir); } bool inside(int r,int c) { if(r>=1&&r<=9&&c>=1&&c<=9) return true; else return false; } int has_edge[Maxn][Maxn][4][3]; int r0,c0,r1,c1,r2,c2,dir; bool read() { char s[99],s2[99]; if(scanf("%s%d%d%s%d%d",s,&r0,&c0,s2,&r2,&c2)!=6) return false; puts(s); dir = dir_id(s2[0]); r1 = r0 + dr[dir]; c1 = c0 + dc[dir]; memset(has_edge,0,sizeof(has_edge)); for(;;) { int r,c; scanf("%d",&r); if(r==0) break; scanf("%d",&c); while(scanf("%s",s)==1&&s[0]!=‘*‘) { for(int i=1; i<strlen(s); i++) { has_edge[r][c][dir_id(s[0])][turn_id(s[i])] = 1; } } } return true; } int d[Maxn][Maxn][4]; Node p[Maxn][Maxn][4]; void print_ans (Node u) { vector<Node> nodes; for(;;) { 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)); int cnt = 0; for(int i=nodes.size()-1; i>=0; i--) { if(cnt%10==0) printf(" "); printf(" (%d,%d)",nodes[i].r,nodes[i].c); cnt++; if(cnt%10==0) printf("\n"); } if(nodes.size()%10!=0) puts(""); } void bfs() { queue<Node> q; memset(d, -1, sizeof(d)); Node u(r1, c1, dir); d[u.r][u.c][u.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; q.push(v); } } } printf(" No Solution Possible\n"); } int main() { while(read()) { bfs(); } return 0; }
以上是关于uva 816 Abbott的复仇的主要内容,如果未能解决你的问题,请参考以下文章
Uva 816 Abbott的复仇(三元组BFS + 路径还原)