题目描述:

输入输出:

输入样例:

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. [LeetCode] 110. Balanced Binary Tree 平衡二叉树

    Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary ...

  2. 转载:Python Web开发最难懂的WSGI协议,到底包含哪些内容?

    原文:PSC推出的第二篇文章-<Python Web开发最难懂的WSGI协议,到底包含哪些内容?>-2017.9.27 我想大部分Python开发者最先接触到的方向是WEB方向(因为总是有 ...

  3. 使用vue开发微信公众号,解决微信缓存

    1.页面加入标红的代码,让页面不缓存 <!DOCTYPE html> <html manifest="IGNORE.manifest"> <head& ...

  4. openstack keystone 命令详细

    命令使用之前需要  运行命令行“. admin-openrc” 用户(User) 查看用户列表 openstack user list 创建用户 openstack user create [-h] ...

  5. LeetCode 541. 反转字符串 II(Reverse String II)

    541. 反转字符串 II 541. Reverse String II

  6. python学习-68 反射

    反射 1.什么是反射? 反射的概念是有Smith在1982年首次提出的,主要是指程序可以访问.检测和修正它本身状态或行为的一种能力(自省). 2.以下四个方法可以实现自省 hasattr(object ...

  7. PHP CLI中,三个系统常量:STDIN、STDOUT、STDERR

    PHP CLI中,有三个系统常量,分别是STDIN.STDOUT.STDERR,代表文件句柄. /** *@ 标准输入 *@ php://stdin & STDIN *@ STDIN是一个文件 ...

  8. AX2009取销售订单的税额

    直接用以下方法即可: Tax::calcTaxAmount(salesLine.TaxGroup, salesLine.TaxItemGroup, systemDateGet(),    salesL ...

  9. C#的WebApi 与 EasyUi的DataGrid结合生成的可分页界面

    1.从数据库每次取出的数据为当前分页的数据. 2.分页用的是EasyUI 的 Pagination控件,与DataGrid是相对独立的. 3.后台数据获取是通过WebApi去获取. 4.传入参数是:p ...

  10. vscode 连接远程服务器 sftp

    1.在vscode 应用商店搜索 sftp 下载安装 2.ctrl+shift+p 搜索sftp:config 生成sftp.json 3.配置你的服务器信息{ "name": & ...