题目链接:https://vjudge.net/problem/UVA-816

题目大意: 有一个最多包含9*9 个交叉点的迷宫。输入起点,离开起点时的朝向和终点,求一条最短路(多解时任意输出 一个即可)

思路:  这个迷宫的特殊之处其实就两点,一是朝向会影响往哪走,而是要记录走的路径。

所以我们要解决这两个难点:

朝向  :我们可以给数组再加一个朝向 来标记是否访问过

记录路径:可以 记录当前节点的父亲节点,注意当前节点是加 了朝向的当前节点

这是写过的第一道要输出路径的题目,很重用!!!

看代码:

#include<iostream>
#include<string.h>
#include<queue>
#include<stdio.h>
using namespace std;
const int maxn=+; struct Node
{
int r,c,dir;//该位置的坐标 和 上一个位置走dir方向到这里
Node(int r=,int c=,int dir=):r(r),c(c),dir(dir){}//构造函数
}; /**
将四个方向和3种“转弯方式”编号 并且提供相应的转换函数
**/
const char* dirs="NESW";//顺时针旋转 下标0-3
const char* turns="FLR";//下标0-2
int dir_id(char c){return strchr(dirs,c)-dirs;}//找到该字符出现的位置
int turn_id(char c){return strchr(turns,c)-turns;} int d[maxn][maxn][maxn];//第一个位置到该位置的距离
int has_edge[maxn][maxn][maxn][maxn];//该节点到下一个地方是否有路
Node p[maxn][maxn][maxn];//该节点的父亲节点
int r0,c0,r1,c1,dir,r2,c2;//起点 下一个节点 终点
string maze_name;//名字 /**
接下来是"行走"函数,根据当前状态和转弯方式 计算出后继状态
**/
const int dr[]={-,,,};//注意顺序不能变 与之前的dirs相对应的
const int dc[]={,,,-}; Node walk(const Node& u,int turn)
{
int dir=u.dir;
if(turn==) dir=(dir+)%;//逆时针 往左走 不管哪个方向 加上3就是它的左边
if(turn==) dir=(dir+)%;//顺时针
return Node(u.r+dr[dir],u.c+dc[dir],dir);//下一个节点的坐标 和 从哪来
} /**
inside
**/
bool inside(int r,int c)
{
if(r>=&&r<=&&c>=&&c<=) return true;
return false;
} /**
最后是解的打印过程。它也可以写成递归函数 不过用vector保存结点可以避免递归时出现栈溢出,并且更加灵活
**/
void print_ans(Node u)
{
//从目标结点逆序追溯到初始结点
vector<Node> nodes;
for(;;)//一直找到除起点外的第一个位置
{
nodes.push_back(u);
if(d[u.r][u.c][u.dir]==) break;
u=p[u.r][u.c][u.dir];
}
nodes.push_back(Node(r0,c0,dir));//起点 cout<<maze_name<<endl; //打印解
int cnt=;
for(int i=nodes.size()-;i>=;i--)
{
if(cnt%==) printf(" ");
printf(" (%d,%d)",nodes[i].r,nodes[i].c);
if(++cnt%==) printf("\n"); }
if(nodes.size()%!=) printf("\n");
return ;
} /**
下面是bfs主过程
**/
void solve()
{
queue<Node> q;
memset(d,-,sizeof(d));
Node u(r1,c1,dir);//起点走到的第一个位置
d[u.r][u.c][u.dir]=;
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=;i<;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]<)//往这个方向有路 并且 这条路合法 并且 没有走过
{
d[v.r][v.c][v.dir]=d[u.r][u.c][u.dir]+;//距离加一
p[v.r][v.c][v.dir]=u;//存储当前节点的父亲节点
q.push(v);//当前节点入队列
}
}
}
cout<<maze_name<<endl;
printf(" No Solution Possible\n");
} /**
输入函数比较简单 作用就是读取r0,c0,dir,并且计算出r1,c1 然后读入has_edge数组中
其中has_edge[r][c][dtr][turn]表示当前状态是(r,c,dir) 是否可以沿着转弯方向turn行走
**/
void read_edge()
{
memset(has_edge,,sizeof(has_edge));//初始化 全都为没有走过
int pr,pc,pdir,pturn;
string temp;
while(cin>>pr)
{
if(pr==) break;
cin>>pc;
while(cin>>temp)
{
if(temp=="*") break;
pdir=dir_id(temp[]);//从哪个方向来的
for(int i=;i<temp.length();i++)
{
pturn=turn_id(temp[i]);
has_edge[pr][pc][pdir][pturn]=;//往哪个方向走有路
}
}
}
} /**
输入函数
**/
bool read_list()
{
cin>>maze_name;//名字
if(maze_name=="END") return false;
char dir0;
cin>>r0>>c0>>dir0>>r2>>c2;//初始位置 方向 结束位置
dir=dir_id(dir0);//计算下一个位置在哪
r1=r0+dr[dir];
c1=c0+dc[dir];
read_edge();
return true;
} int main()
{
while(read_list())
{
solve();
}
return ;
}

其实自己也把这道题写出来了,代码将近写了300行,但是虽然结果正确了,但是交上去却显示re   找了很久的Bug  没找出来,无奈之下看了题解才过掉

到现在自己也没有找出Bug在哪 ,还是自己太菜了

Abbott's Revenge UVA - 816 (输出bfs路径)的更多相关文章

  1. 【紫书】【重要】Abbott's Revenge UVA - 816 bfs 复杂模拟 带方向参数的迷宫

    题意:一个迷宫,每个交叉路口有一路标,限制了你从某方向进入该路口所能进入的路口. 题解:1.对于方向的处理:将node多增加一维dir,通过一个const 字符数组 加 上dir_id函数 以及一个方 ...

  2. BFS求最短路 Abbottt's Revenge UVa 816

    本题的题意是输入起点,朝向和终点,求一条最短路径(多解时任意输出一个即可) 本题的主要代码是bfs求解,就是以下代码中的slove的主要部分,通过起点按照路径的长度来寻找最短路径,输出最先到终点的一系 ...

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

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

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

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

  5. L - Abbott's Revenge(比较复杂的bfs)

    Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UV ...

  6. UVa 816 (BFS求最短路)

    /*816 - Abbott's Revenge ---代码完全参考刘汝佳算法入门经典 ---strchr() 用来查找某字符在字符串中首次出现的位置,其原型为:char * strchr (cons ...

  7. UVa816 Abbott's Revenge

    Abbott's Revenge Time limit: 3.000 seconds Abbott’s Revenge  Abbott’s Revenge The 1999 World FinalsC ...

  8. 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, ...

  9. 老鼠走迷宫(2)输出所有路径(C语言)

    需求 有一个迷宫,在迷宫的某个出口放着一块奶酪.将一只老鼠由某个入口处放进去,它必须穿过迷宫,找到奶酪.请找出它的行走路径. STEP 1 题目转化 我们用一个二维数组来表示迷宫,用2表示迷宫的墙壁, ...

随机推荐

  1. Java50道经典习题-程序26 求星期

    题目:请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续 判断第二个字母.分析:用情况语句比较好,如果第一个字母一样,则判断用情况语句或if语句判断第二个字母.周一至周日的英文单词 ...

  2. Python中dataframe\ array\ list相互转化

    import pandas as pd import numpy as np #创建列表 a1=[1,2,3] #arange函数:指定初始值.终值.步长来创建数组 a2=np.arange(0,1, ...

  3. baidumap应用

    需要在安卓平台利用baidumap SDK进行二次开发, 注册好,创建应用 利用jdk/bin里的keytool做Android SDK安全码 进入.android(参照下图):输入keytool - ...

  4. [MOOC程序设计与算法二] 递归二

    1.表达式计算 输入为四则运算表达式,仅由整数.+.-.* ./ .(.) 组成,没有空格,要求求其值.假设运算符结果都是整数 ."/"结果也是整数 表达式也是递归的定义: 表达式 ...

  5. PHP 符号

    注解符号: // 单行注解 /*      */    多行注解 引号的使用 ’   ’ 单引号,没有任何意义,不经任何处理直接拿过来; " "双引号,PHP动态处理然后输出,一般 ...

  6. Liunx配置静态IP

    刚开始Linux默认的是动态获取,而我们需要设置静态IP(我是为了xshell的连接) 1.  执行dhclient命令自动获取到一个IP,NETMASK, 2.  执行route命令,获取defau ...

  7. HDU6298 Maximum Multiple (多校第一场1001)

    Maximum Multiple Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  8. LUNA16数据集(二)肺结节可视化

    在检测到肺结节后,还需要可视化,这样才能为诊断服务. 我使用的项目地址为:https://github.com/wentaozhu/DeepLung 项目基于论文:DeepLung: Deep 3D ...

  9. CSS+jQuery实现轮播

    CSS+jQuery实现轮播 CSS jQuery 前端  实现功能: 自动轮播: 鼠标放在上面停止轮播: 鼠标放在上面显示左右切换的按钮: 鼠标放在小圆圈上显示对应的图片: 轮播效果图 style. ...

  10. 使用npm发布自己的包

    记录一下大概步骤: 去npm官网注册一个账号 在文件夹下执行npm init 创建 package.json 执行 npm login,并根据提示输入你的npm账号,密码,和邮箱 执行 npm pub ...