题意:

有一个最多9*9个点的迷宫, 给定起点坐标(r0,c0)和终点坐标(rf,cf), 求出最短路径并输出。

分析:

因为多了朝向这个元素, 所以我们bfs的队列元素就是一个三元组(r,c,dir),然后做好输入处理的细节, 这题的关键在于bfs中的路径还原。

其实bfs的过程就是一棵树,如下图

除了起点外, 每个点都有且只有一个父亲节点, 那么我们只需要开一个pre数组来记录每个点的父亲, 找到终点后从终点往上不断找父亲节点, 直到找到父亲节点, 那么就完成了路径还原的

步骤。

 #include <bits/stdc++.h>
using namespace std;
struct Node{
int r,c,dir;
Node(int r=, int c=, int dir=):r(r),c(c),dir(dir) {}
}; int have_edge[][][][];
int d[][][];
Node pre[][][];
int r0,c0,r1,c1,rf,cf,init_dir;
const char* dirs = "NESW"; //
const char* turns = "FLR";//0不动 1左 顺时针 2右 逆时针 int id_dir(char s){ return strchr(dirs,s) - dirs;}
int id_turn(char s){return strchr(turns,s) - turns;} const int dr[] = {-, , , }; //dirs为上右下左
const int dc[] = {, , , -}; bool input(){
char s1[], s2[];
int o;
if((o = scanf("%s%d%d%s%d%d",s1,&r0,&c0,s2,&rf,&cf) )!= ) { return false;}
printf("%s\n", s1);
init_dir = id_dir(s2[]);
r1 = r0 + dr[init_dir];
c1 = c0 + dc[init_dir];
// printf("%d %d %d\n", init_dir,r1,c1);
memset(have_edge,,sizeof(have_edge));
for(;;){
int r,c;
scanf("%d", &r);
if(r == ) break;
scanf("%d", &c);
while(scanf("%s", &s2) && s2[] != '*'){
int len = strlen(s2);
for(int i = ; i < len; i++){
have_edge[r][c][id_dir(s2[])][id_turn(s2[i])] = ;
}
}
}
return true;
}
Node walk(const Node& u, int turn){
int dir = u.dir;
if(turn == ) dir = (u.dir+)%;
else if(turn == ) dir = (u.dir+) %;
return Node(u.r + dr[dir], u.c + dc[dir] , dir);
} bool inside(int r, int c) {
return r >= && r <= && c >= && c <= ;
}
void print_ans(Node u){
vector<Node> ans;
for(;;){
ans.push_back(u);
if(d[u.r][u.c][u.dir] == )
break;
u = pre[u.r][u.c][u.dir];
}
ans.push_back(Node(r0,c0,init_dir)); int cnt = ;
for(int i = ans.size() -; i >= ; i--){
if(cnt % == ) printf(" ");
printf(" (%d,%d)", ans[i].r, ans[i].c);
if(++cnt % == ) printf("\n");
}
if(ans.size() % != ) printf("\n");
}
void solve(){
queue<Node> q;
memset(d,-,sizeof(d));
d[r1][c1][init_dir] = ;
Node u(r1,c1,init_dir);
q.push(u);
while(!q.empty()){
Node u = q.front(); q.pop();
// printf("$ u %d %d %d\n",u.r, u.c,u.dir);
if(u.r == rf && u.c == cf){
print_ans(u);
return;
}
for(int i = ; i < ; i++){
Node v;
if(have_edge[u.r][u.c][u.dir][i])
v = walk(u,i);
// printf("& v %d %d %d\n",v.r, v.c, v.dir);
if(inside(v.r,v.c) && d[v.r][v.c][v.dir] < ){
d[v.r][v.c][v.dir] = d[u.r][u.c][u.dir] + ;
pre[v.r][v.c][v.dir] = u;
q.push(v);
}
}
}
printf(" No Solution Possible\n");
}
int main(){
while(input()){
solve();
}
return ;
}

Uva 816 Abbott的复仇(三元组BFS + 路径还原)的更多相关文章

  1. UVa 816 Abbott的复仇(BFS)

    寒假的第一道题目,在放假回家颓废了两天后,今天终于开始刷题了.希望以后每天也能多刷几道题. 题意:这道BFS题还是有点复杂的,给一个最多9*9的迷宫,但是每个点都有不同的方向,每次进入该点的方向不同, ...

  2. uva 816 Abbott的复仇

    题目链接:https://uva.onlinejudge.org/external/8/816.pdf 紫书:P165 题意: 有一个最多包含9*9个交叉点的迷宫.输入起点.离开起点时的朝向和终点,求 ...

  3. UVA - 816 Abbott's Revenge(bfs)

    题意:迷宫从起点走到终点,进入某点的朝向不同,可以出去的方向也不同,输出最短路. 分析:因为朝向决定接下来在该点可以往哪里走,所以每个点需要有三个信息:x,y,d(坐标和进入该点的朝向),所以将起点的 ...

  4. UVA 816 -- Abbott's Revenge(BFS求最短路)

     UVA 816 -- Abbott's Revenge(BFS求最短路) 有一个 9 * 9 的交叉点的迷宫. 输入起点, 离开起点时的朝向和终点, 求最短路(多解时任意一个输出即可).进入一个交叉 ...

  5. UVA 816 - Abbott&#39;s Revenge(BFS)

    UVA 816 - Abbott's Revenge option=com_onlinejudge&Itemid=8&page=show_problem&category=59 ...

  6. POJ-3894 迷宫问题 (BFS+路径还原)

    定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, ...

  7. uva 816 - Abbott&#39;s Revenge(有点困难bfs迷宫称号)

    是典型的bfs,但是,这个问题的目的在于读取条件的困难,而不是简单地推断,需要找到一种方法来读取条件.还需要想办法去推断每一点不能满足条件,继续往下走. #include<cstdio> ...

  8. Uva 816 Abbott's Revenge(BFS)

    #include<cstdio> #include<cstring> #include<vector> #include<queue> using na ...

  9. UVA 816 Abbott’s Revenge

    bfs求最短路,递归打印最短路的具体路径: 难点: 当前状态和转弯方式很复杂,要仔细处理: 递归打印:用一个数组存储路径中结点的前一个节点,递归查找 (bfs无法确定下一个结点,但对于没一个结点,它的 ...

随机推荐

  1. win7 右键菜单残影 消除方法

    1. 治标法: 右键桌面->更改分辨率  随便换一个分辨率再还原就OK了! 2. 根治法: 我的电脑-> 属性 ->高级选项-> 高级-> 设置-> 自定义   不 ...

  2. [ZOJ1140]Courses 课程

    Description 给出课程的总数P(1<=p<100),学生的总数N(1<=N<=300) 每个学生可能选了一门课程,也有可能多门,也有可能没有. 要求选出P个学生来组成 ...

  3. 洛谷 P2048 [NOI2010]超级钢琴 || Fantasy

    https://www.luogu.org/problemnew/show/P2048 http://www.lydsy.com/JudgeOnline/problem.php?id=2006 首先计 ...

  4. 转】Cassandra单集群实验2个节点

    原博文出自于: http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/3/ 感谢! Cassandra单集群实验2个节点 前言 A ...

  5. (五)SpringIoc之Bean的作用域

    此文转自 https://blog.csdn.net/icarus_wang/article/details/51586776# 有状态bean和无状态bean请看 https://blog.csdn ...

  6. 关于 user agent ua

    1.ua介绍: ua查询参考网址:http://www.atool.org/useragent.php(也可以自己制作html查询) js 属性:navigator.userAgent 使用方法:将网 ...

  7. 面试题9-用两个栈来实现一个队列,完成队列的Push和Pop操作

    题目 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路: 一个栈压入元素,而另一个栈作为缓冲,将栈1的元素出栈后压入栈2中 代码 import java.ut ...

  8. OC语言Block 续

    OC语言 Block 转载:http://blog.csdn.net/weidfyr/article/details/48138167 1.Block对象中的变量行为 结论: 在block代码块内部可 ...

  9. Node.js——Stream

    介绍 文件流:我们一般对大一点的文件实现stream的方式进行操作 http:显然http.createServer创建过程中的IncomingMessage实现了可读流的接口,ServerRespo ...

  10. CAD参数绘制直径标注(com接口)

    主要用到函数说明: _DMxDrawX::DrawDimDiametric 绘制一个直径标注.详细说明如下: 参数 说明 DOUBLE dChordPointX 在被标注的曲线上的第一个点X值 DOU ...