UVA816 Abbott's Revenge (三元组BFS)
题目描述:
输入输出:
输入样例:
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)的更多相关文章
- UVa816 Abbott's Revenge
Abbott's Revenge Time limit: 3.000 seconds Abbott’s Revenge Abbott’s Revenge The 1999 World FinalsC ...
- UVA - 816 Abbott's Revenge(bfs)
题意:迷宫从起点走到终点,进入某点的朝向不同,可以出去的方向也不同,输出最短路. 分析:因为朝向决定接下来在该点可以往哪里走,所以每个点需要有三个信息:x,y,d(坐标和进入该点的朝向),所以将起点的 ...
- UVA 816 -- Abbott's Revenge(BFS求最短路)
UVA 816 -- Abbott's Revenge(BFS求最短路) 有一个 9 * 9 的交叉点的迷宫. 输入起点, 离开起点时的朝向和终点, 求最短路(多解时任意一个输出即可).进入一个交叉 ...
- UVA 816 - Abbott's Revenge(BFS)
UVA 816 - Abbott's Revenge option=com_onlinejudge&Itemid=8&page=show_problem&category=59 ...
- L - Abbott's Revenge(比较复杂的bfs)
Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Status Practice UV ...
- Abbott's Revenge UVA - 816 (输出bfs路径)
题目链接:https://vjudge.net/problem/UVA-816 题目大意: 有一个最多包含9*9 个交叉点的迷宫.输入起点,离开起点时的朝向和终点,求一条最短路(多解时任意输出 一个即 ...
- Uva 816 Abbott的复仇(三元组BFS + 路径还原)
题意: 有一个最多9*9个点的迷宫, 给定起点坐标(r0,c0)和终点坐标(rf,cf), 求出最短路径并输出. 分析: 因为多了朝向这个元素, 所以我们bfs的队列元素就是一个三元组(r,c,dir ...
- UVA-816.Abbott's Tevenge (BFS + 打印路径)
本题大意:给定一个迷宫,让你判断是否能从给定的起点到达给定的终点,这里起点需要输入起始方向,迷宫的每个顶点也都有行走限制,每个顶点都有特殊的转向约束...具体看题目便知... 本题思路:保存起点和终点 ...
- 【例题 6-14 UVA-816】Abbott's Revenge
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 预处理出某个方向的左边.前边.右边是哪个方向就好了. 然后就是普通的bfs了. hash存到某个点,走到这里的方向的最小距离. df ...
随机推荐
- MongoDB的局域网连接问题
问题前两天在本机连接虚拟机的MongoDB,总是连接拒绝 上网百度了一堆,找到一些看似解释,实则不一定管用的玩意. 自己找到一个解法是改etc/mongodb.conf文件,把bindIp的127.0 ...
- 【SSH进阶之路】Spring的AOP逐层深入——采用注解完成AOP(七)
上篇博文[SSH进阶之路]Spring的AOP逐层深入——AOP的基本原理(六),我们介绍了AOP的基本原理,以及5种通知的类型, AOP的两种配置方式:XML配置和Aspectj注解方式. 这篇我们 ...
- react前端模版Material-UI.类似于antd/bootstrap
Material-UI Material-UI是一个实现了Google's Material Design设计规范的react组件库,开箱即用,使用它可以快速搭建出赏心悦目的应用界面. 文档 各种模版 ...
- DHCP的配置方法
1.实验拓扑图: 2.配置命令: AR2: <Huawei>system-view[Huawei]dhcp enable #开启DHCP服务[Huawei]interface G ...
- 了解一下JVM和GC工作机制
题外话:很久没有写博客了,事情颇多,今天空闲下来,学习一下顺便写一下自己的了解,机会总是留给有准备的人,所以平常一定要注意知识的巩固和积累.知识的深度也要有一定的理解,不比别人知道的多,公司干嘛选你? ...
- 小程序重置index,重置item
重置index,重置item <block wx:for="{{index_data.banner_list}}" wx:for-index="idx" ...
- 【程序人生】Oracle正式公布裁员,1600人,补偿N+6
早些时候Oracle内部员工透漏,Oracle中国研发中心(CDC)或彻底关闭,涉及约1600名工程师的命运. 今天甲骨文正式公布裁员,整个中国研发中心关闭,补偿是全员n+6,包括北京,苏州,南京,上 ...
- SQL——ORDER BY关键字
一.ORDER BY关键字用法 ORDER BY关键字用于对数据进行排序,默认ASC(升序),可以DESC关键字变为降序. ORDER BY关键字语法: SELECT * from 表名 WHERE ...
- array_walk、array_map、array_filter 的用法
array_walk.array_map.array_filter 和 foreach 都有循环对数组元素进行处理的功能. 一.array_walk 用法 1.循环数组,回调处理(并不修改数组元素的 ...
- 作为一个纯粹数据结构的 Redis Streams
来源:antirez 翻译:Kevin (公众号:中间件小哥) Redis 5 中引入了一个名为 Streams 的新的 Redis 数据结构,吸引了社区极大的兴趣.接下来,我会在社区里进行调查,同用 ...