题目描述:

输入输出:

输入样例:

SAMPLE
3 1 N 3 3
1 1 WL NR *
1 2 WLF NR ER *
1 3 NL ER *
2 1 SL WR NF *
2 2 SL WF ELF *
2 3 SFR EL *
0
NOSOLUTION
3 1 N 3 2
1 1 WL NR *
1 2 NL ER *
2 1 SL WR NFR *
2 2 SR EL *
0
END
输出样例:
SAMPLE
(3,1) (2,1) (1,1) (1,2) (2,2) (2,3) (1,3) (1,2) (1,1) (2,1)
(2,2) (1,2) (1,3) (2,3) (3,3)
NOSOLUTION
No Solution Possible
思路:
将普通图(只含有两个方向的平面图)改为三元组表示的图,再在“平面图”的基础上调用BFS算法,求单元最短路径。输入输出很繁(对我这个菜鸡来说)。
还有就是行走函数根据转向不同将char类型的方向映射到两个一维的int上去的方式很巧妙(巧妙的加3加1取余4,就打乱原来的NESW逆时针顺序),
再通过dr,dc数组实现方向的变化和移动。注意初始位置(r1,c1)不是原始位置(r0,c0)。
开始将d数组初始化为-1,到d[r1][c1][dir]就为0(加了1)。所以在用vector反着打印路径时最后加一个(r0,c0)(未存)
代码:(有详细的但也难懂的注释)
 #include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#define max_n 10
using namespace std;
struct Node
{
int r;
int c;
int dir;
Node(int r1=,int c1=,int d1=) :r(r1),c(c1),dir(d1) {}
//构造Node,带有默认参数,不然会在Node p[][][]那里报错,认为这个语句是在构造Node
};
int d[max_n][max_n][];//表示初始状态到(r,c,dir)的最短路长度
Node p[max_n][max_n][];//保存了状态(r,c,dir)在BFS数中的父结点
int has_edge[max_n][max_n][][];//当前状态是(r,c,dir),是否可以沿着转弯方向turn行走 //行走
const char* dirs = "NESW"; //顺时针旋转的顺序
const char* turns = "FLR";
int dir_id(char c) {return strchr(dirs,c)-dirs;} //将char类型的dir转化为dirs中相应的所在位置
int turn_id(char c) {return strchr(turns,c)-turns;}//将char类型的turn在turns中找到对应的元素位置
const int dr[] = {-,,,};//用上面找到的元素位置来确定当前行行走方向
const int dc[] = {,,,-};//用上面找到的元素位置来确定当前列行走方向
char maze[];//迷宫名称
int r0,c0,dir;//原始位置和方向
int r1,c1;//初始位置和方向
int r2,c2;//目标位置
//巧妙的行走函数和对应关系
//dirs 0N 1E 2S 3W
//顺时针
//dir' 3 0 1 2
//逆时针
//dir' 1 2 3 0
//dr -1 0 1 0
//dc 0 1 0 -1
Node walk(const Node& u,int turn)
{
int dir = u.dir;
if(turn==) dir = (dir+)%;
if(turn==) dir = (dir+)%;
return Node(u.r+dr[dir],u.c+dc[dir],dir);
}
//判断越界函数
int inside(int r,int c)
{
return <r&&r<=&&<c&&c<=;
}
//输出函数
//要求:
//第一行输出迷宫名
//后几行输出路径,且除最后一行外,其他每行都是空两格+10个(r,c)形式空格分隔的坐标
void printa(Node u)
{
vector<Node> nodes;//可用递归方式打印,但可能溢栈,可改用循环,用vector存储
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)); int cnt = ;
for(int i = nodes.size()-;i>=;i--)
{
if(cnt%==) //值得品味的细节1
{
printf(" ");
}
printf(" (%d,%d)",nodes[i].r,nodes[i].c);
if(++cnt%==)//值得品味的细节2
{
printf("\n");
}
}
if(nodes.size()%!=)
{
printf("\n");
}
}
//输入函数
//先读入迷宫名,若为END返回0,
//然后一行读入起点r,c,dir,终点r,c
//然后处理交叉处的方向改变,将这些信息用数组has_edge[r][c][dir][turn]记录下来,为以后BFS提供基础
//读到*结束小循环,读到0结束大循环
int read()
{
cin >> maze;
if(maze[]=='E'&&maze[]=='N'&&maze[]=='D'&&strlen(maze)==) return ;
cout << maze << endl;
memset(maze,,sizeof(maze[])); char dirs;
cin >> r0 >> c0 >> dirs >> r2 >> c2;
dir = dir_id(dirs);
r1 = r0+dr[dir];
c1 = c0+dc[dir];
memset(has_edge,,sizeof(has_edge)); for(;;)
{
int r,c;
cin >> r;
if(r==)
{
break;
}
cin >> c;
char chr[];
while(cin >> chr)
{
if(chr[]=='*')
{
break;
}
for(int i = ;i<strlen(chr);i++)
{
has_edge[r][c][dir_id(chr[])][turn_id(chr[i])] = ;
}
//cout << r << " " << c << " " << chr << endl;
memset(chr,,sizeof(chr[]));
}
}
return true;
}
//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)
{
printa(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);
} }
}
printf(" No Solution Possible\n");
}
int main()
{
while(read())
solve();
return ;
}

UVA816 Abbott's Revenge (三元组BFS)的更多相关文章

  1. UVa816 Abbott's Revenge

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

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

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

  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. Abbott's Revenge UVA - 816 (输出bfs路径)

    题目链接:https://vjudge.net/problem/UVA-816 题目大意: 有一个最多包含9*9 个交叉点的迷宫.输入起点,离开起点时的朝向和终点,求一条最短路(多解时任意输出 一个即 ...

  7. Uva 816 Abbott的复仇(三元组BFS + 路径还原)

    题意: 有一个最多9*9个点的迷宫, 给定起点坐标(r0,c0)和终点坐标(rf,cf), 求出最短路径并输出. 分析: 因为多了朝向这个元素, 所以我们bfs的队列元素就是一个三元组(r,c,dir ...

  8. UVA-816.Abbott's Tevenge (BFS + 打印路径)

    本题大意:给定一个迷宫,让你判断是否能从给定的起点到达给定的终点,这里起点需要输入起始方向,迷宫的每个顶点也都有行走限制,每个顶点都有特殊的转向约束...具体看题目便知... 本题思路:保存起点和终点 ...

  9. 【例题 6-14 UVA-816】Abbott's Revenge

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 预处理出某个方向的左边.前边.右边是哪个方向就好了. 然后就是普通的bfs了. hash存到某个点,走到这里的方向的最小距离. df ...

随机推荐

  1. 算法练习之二叉树的最大深度,二叉树的层次遍历 II

    1.二叉树的最大深度 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例:给定二叉树 [3,9,20,null,n ...

  2. VS2013+OpenCV3.4.2编译

    一.准备工作: (1)在OpenCV官网下载3.4.2版本(注意选择Win pack),https://opencv.org/releases.html. (2)下载Contrib模块,https:/ ...

  3. android基础---->WebView的使用

    webView的使用 我们通过一个小的测试程序来体会webView的简单使用,项目结构如下:

  4. django models.update

    json/dict类型数据更新字段目前主流的web开放方式都讲究前后端分离,分离之后前后端交互的数据格式大都用通用的jason型,那么如何用最少的代码方便的更新json格式数据到数据库呢?同样可以使用 ...

  5. QT5 添加resource的方法

    在工程中右键点击xxx.qrc文件,选择"open in editor",然后可以用"Add ""Remove"按钮进行资源文件的添加.

  6. mysql 按照两个字段之和进行排序

    SELECT *,zan_num+fake_zan_num show_zan FROM `tf_news` order by show_zan desc TP实现 $news = M('news'); ...

  7. PMBOK(第六版) PMP备考知识总汇!

    记录本人学习PMBOK第六版的学习笔记. 备考知识总汇! PMBOK序章 PMP备考指南之相关事项介绍 PMP备考指南之第一章:引论 PMP备考指南之第二章:项目运作环境 PMP备考指南之第三章:项目 ...

  8. 嵌入式02 STM32 实验04跑马灯

    开学STM32 跑马灯的实验主要就是了解GPIO口的配置及使用,我这里是使用库函数进行编程,主要需要设置以下两方面: 1.使能需要使用的IO口的时钟,一共有A.B.C.D.E.F.G七组IO口 2.初 ...

  9. python基础 — random库

    python中用于生成伪随机数的函数库是random 因为是标准库,使用时候只需要import random random库包含两类函数,常用的共8个 --基本随机函数: seed(), random ...

  10. tidb测试环境搭建

    tidb ansible 部署方式环境检查过于严格,测试环境往往达不到标准,需调整一些参数才能部署成功. 基于tidb2.0版本需要调整的参数 [tidb@ansible01 tidb-ansible ...