题目描述:

输入输出:

输入样例:

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. 【神经网络与深度学习】Win10+VS2015 caffe环境搭建(极其详细)

    caffe是好用,可是配置其环境实在是太痛苦了,依赖的库很多不说,在VS上编译还各种报错,你能想象那种被一百多个红色提示所笼罩的恐惧.  且网上很多教程是VS2013环境下编译的,问人很多也说让我把1 ...

  2. Maven打包报错:[WARNING] The POM for xxx is missing, no dependency inform

    maven install 或 package 时 ,执行警告报错: [WARNING] The POM for com.xx-base:jar:1.0 is missing, no dependen ...

  3. 解决ViewPager与百度地图滑动冲突

    一.问题描述 ViewPager中嵌套百度地图的时候会出现百度地图滑动冲突. 二.期望结果: 滑动地图的时候只有地图滑动,滑动其他区域可以切换viewpager. 三.解决方法 自定义viewpage ...

  4. TCP/IP学习笔记3--传输方式的分类

    网络通信中有多中分类方法: )分组较短.出错几率降低,每次重发的数据量也降低,不仅提高了可靠性,也降低了时延.缺点:(1)因为数据进入交换节点后要经历存储转发这一过程,从而引起的转发时延(包含接受分组 ...

  5. vue通过ajax加载json数据

    HTML <ul id="Hanapp"> <li class="styVue" v-for="item in actList&qu ...

  6. [转帖]直击案发现场!TCP 10倍延迟的真相是?

    直击案发现场!TCP 10倍延迟的真相是? http://zhuanlan.51cto.com/art/201911/605268.htm 内核参数调优 非常重要啊. 什么是经验?就是遇到问题,解决问 ...

  7. 【C++札记】虚继承

    由于多重继承产生的二义性引入了类的虚继承,先看下什么是二义性. 类D是类B和类C的派生类,而类B,类C就是继承于类A,当D调用类A中的函数时不知道是类B继承A的,还是类C继承A的,引起了二义性.虚继承 ...

  8. 如何用navicat导入数据?

    介绍了如何使用navicat导入数据到数据库 0背景介绍 这里用的软件版本号是11.2.7 1选择要导入的数据库,右击选择导入向导 2 选择导入数据文件的类型 根据要导入数据文件的类型,选择对应的导入 ...

  9. springboot 2.1.3.RELEASE添加filter,servlet源码学习

    Servlet规范中,通过ServeltContext来注册Filter.Servlet,这里分析Filter,Servlet是相同逻辑 springboot2.0中,我们通过 FilterRegis ...

  10. 文件流CopyTo