题意:

有一个最多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. 我的spring cloud项目历程(2018.3~2018.9)

    前言 今天是9月17日,趁着山竹的临幸,得以在家里舒适的办公.项目从3月底开始,至今刚好半年.抽几十分钟,总结下半年的历程.对后面的项目,应该也有一点帮助吧. 学习前的七个问题 项目开始前,由于某些特 ...

  2. 《windows核心编程系列 》六谈谈线程调度、优先级和关联性

    线程调度.优先级和关联性 每个线程都有一个CONTEXT结构,保存在线程内核对象中.大约每隔20ms windows就会查看所有当前存在的线程内核对象.并在可调度的线程内核对象中选择一个,将其保存在C ...

  3. A - Add More Zero

    Bryce1010模板 #include <bits/stdc++.h> using namespace std; #define LL long long int main() { in ...

  4. bryce1010专题训练——线段树习题汇总

    一.区间查询,无单点更新 hdu2795 Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  5. android将对象序列化到文件:直接写文件与用Serializable接口的对比

    1.用文件读写1024个对象的日志 10-09 16:12:44.493 6385-6385/com.example.tt.downtest D/Serializable_TAG: write 102 ...

  6. C# winform与Javascript的相互调用[转]

    原文链接<html> <head> <meta http-equiv="Content-Language" content="zh-cn&q ...

  7. Spring注解驱动开发之扩展原理

    前言:现今SpringBoot.SpringCloud技术非常火热,作为Spring之上的框架,他们大量使用到了Spring的一些底层注解.原理,比如@Conditional.@Import.@Ena ...

  8. IO流的原理和概念

    在程序中如何读写文件?不同的编程语言有不同的方式,而 JAVA 则提出了“流”的概念,通过“流”来读写文件 什么是流: 流(Stream)是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通 ...

  9. AJPFX关于throw、throws关键字的解析

    throw.throws关键字 throw关键字: 是用于方法体内部,用来抛出一个Throwable类型的异常.如果抛出了检查异常, 则还应该在方法头部声明方法可能抛出的异常类型.该方法的调用者也必须 ...

  10. 使用iconfont管理项目中的字体图标

    先来说说字体图标的好处: 很容易任意地缩放: 很容易地改变颜色: 很容易地产生阴影: 可以拥有透明效果: 一般来说,有先进的浏览器支持: 可以使用CSS来装饰(可以得到CSS很好支持): 可以快速转化 ...