题意:有一个最多包含9*9个交叉点的迷宫。输入起点,离开起点时的朝向和终点,求一条最短路(多解时任意输出一个即可)。
这个迷宫的特殊之处在于:进入一个交叉点的方向(用NEWS这四个字母分别表示北东西南,即上右左下)不同,允许出去的方向也不同。例如,1 2 WLF NR ER 表示交叉点(1,2)(上数第1行,左数第2列)有3个路标(字符“”只是结束标志),如果进入该交叉点时的朝向为W(即朝左),则可以左(L)或者直行(F);如果进入时朝向为N或者E则只能右转(R),如图6-14所示。
注意:初始状态是“刚刚离开入口”,所以即使出口和入口重合,最短路也不为空。例如,图6-14中的一条最短路为(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)。

【分析】
本题和普通的迷宫在本质上是一样的,但是由于“朝向”也起到了关键作用,所以需要用到一个三元组(r,c,dir)表示“位于(r,c),面朝dir”这个状态。假设入口位置为(r0,c0),朝向为dir,则初始状态并不是(r0,c0,dir),而是(r1,c1,dir),其中,(r1,c1)是(r0,c0)沿着方向p[r][c][dir]保存了状态(r,c,dir)在BFS树中的父节点。

提示6-22:很多复杂的迷宫问题都可以转化为最短路为题,然后用BFS求解。在套用BFS框架之前,需要先搞清楚图中的“结点”包含哪些内容。
以上内容来自《算法竞赛入门经典》

补充:开一个数组has_edge[r][c][dir1][dri2],表示(r,c)这个点转向方式(dir1,dir2)是否可行。path记录路径,step记录步数(起走过的状态标记作用)。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 15;
const char* dirs = "NESW"; //顺时针旋转
const char* turns = "FLR";
const int Dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};//四个方向
int sr0, sc0, sr, sc, sdir, er, ec, edir;//起点(sr, sc, sdir),终点(er, ec, edir),edir是BFS后得到的
char name[100];//地图名称
bool has_edge[MAXN][MAXN][5][5];//该点能走的方向
struct Node
{int r, c, dir; // 站在(r,c),面朝方向dir(0~3分别表示N, E, S, W)Node(int r=0, int c=0, int dir=0):r(r), c(c), dir(dir) {}
};
int step[MAXN][MAXN][5];//vis作用和记录步数
Node path[MAXN][MAXN][5];//记录路径
int dir_id(char c) { return strchr(dirs, c) - dirs; }
int turn_id(char c) { return strchr(turns, c) - turns; }
bool read_case()
{char temp[100];//开成字符串,跳过两个数字之间的空格if (scanf("%s%d%d%s%d%d", name, &sr0, &sc0, temp, &er, &ec) != 6) return false;sdir = dir_id(temp[0]);sr = sr0 + Dir[sdir][0];sc = sc0 + Dir[sdir][1];memset(has_edge, 0, sizeof(has_edge));int r, c;while (~scanf("%d", &r) && r){scanf("%d", &c);char s[100];while (~scanf("%s", s) && s[0] != '*'){for(int i = 1; i < strlen(s); i++)has_edge[r][c][dir_id(s[0])][turn_id(s[i])] = true;}}return true;
}
Node walk(const Node& u, int turn)
{int dir = u.dir;if (turn == 1) dir = (dir + 3) % 4;if (turn == 2) dir = (dir + 1) % 4;return Node(u.r + Dir[dir][0], u.c + Dir[dir][1], dir);
}
bool BFS()
{memset(step, -1, sizeof(step));path[sr][sc][sdir] = Node(sr0, sc0, sdir);//记录第一步step[sr][sc][sdir] = 0;queue<Node> Q;Q.push(Node(sr, sc, sdir));while (!Q.empty()){Node u = Q.front(); Q.pop();if (u.c == ec && u.r == er) { edir = u.dir; return true; }for (int i = 0; i < 3; i++)//3种转向方式{Node v = walk(u, i);if (v.r >= 1 && v.c >= 1 && v.r <= 9 && v.c <= 9&& has_edge[u.r][u.c][u.dir][i] && step[v.r][v.c][v.dir] < 0){step[v.r][v.c][v.dir] = step[u.r][u.c][u.dir] + 1;path[v.r][v.c][v.dir] = u;Q.push(v);}}}return false;
}
void print_ans()
{vector<Node> ans;Node u(er, ec, edir);while (1){ans.push_back(u);if (u.r == sr0 && u.c == sc0) break;u = path[u.r][u.c][u.dir];}int cnt = 0;for (int i = ans.size()-1; i >= 0; i--){if (cnt % 10 == 0) printf(" ");printf(" (%d,%d)", ans[i].r, ans[i].c);if(++cnt % 10 == 0 || i == 0) printf("\n");}
}
int main()
{//freopen("C:\\Users\\张松超\\Desktop\\in.txt", "r", stdin);//freopen("C:\\Users\\张松超\\Desktop\\out.txt", "w", stdout);while (read_case()){printf("%s\n", name);if (BFS()) print_ans();else printf("  No Solution Possible\n");}return 0;
}

UVA ~ 816 ~ Abbott's Revenge (BFS + 打印路径)相关推荐

  1. 816 - Abbott's Revenge

    Abbott's Revenge PS:因为该题排版较麻烦,这里给出OJ网址:UVa816 - Abbott's Revenge 有一个最多包含9*9个交叉点的迷宫.输入起点.离开起点时的朝向和终点, ...

  2. hdu-1104-Remainder(BFS打印路径+数论)(%与mod的区别)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1104 题意:(注意题目中的%是指mod)开始给了你n, k, m....每次由+m, -m, *m, ...

  3. uva816 Abbott's Revenge (BFS+回溯)

    题目大意 给你个迷宫,求最短路,不过在每个点转弯的方向受进入方向的限制 思路 确定好每个点的状态,再用bfd求出最短路,注意记得用个数组保存节点,以方便输出 事实上很多细节都是参考刘汝佳老师的,感觉非 ...

  4. UVa 816 (BFS求最短路)

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

  5. Abbott's Revenge UVA - 816 (输出bfs路径)

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

  6. Frog Traveler 最短路,bfs剪枝,打印路径

    题意 : 给两个长度为n的数组,初始位于索引n,目标是越过索引1,注意不能往后跳,每次可以跳0到a[i]a[i]a[i]米,即,身处索引iii,可以跳[0,a[i]][0, a[i]][0,a[i]] ...

  7. 迪杰斯特拉算法及变式(最短距离,打印路径,最短经过节点数)

    问题描述 给定一个图,图的节点名称用(000 ~ N−1N - 1N−1)表示.NNN为图的节点个数,MMM为边的个数,SSS为起始点. 输入条件: 第一行输入 NMSN M SNMS. 其后MMM行 ...

  8. 7-4 最短路径之Dijkstra(朴素dijkstra打印路径)

    作者 龚雄兴 单位 湖北文理学院 本题目要求通过读入无向网的边的信息(省略了各顶点的信息,仅用顶点编号来表示),构造图,并利用Dijkstra算法,求出指定源点到其它各点的最短路径. 样例" ...

  9. [论文学习笔记]01一种轮廓平行扫描算法【3D打印路径规划】

    文章目录 零.论文来源 0.1 概述 一.算法描述 1.1 定义一些概念 1.2 域分区 1.3 偏移量的生成 1.4 自交问题 1.5 尖角 1.6 外部轮廓和内部轮廓相交 1.7 空隙 1.8 连 ...

  10. POJ 3414 Pots(深搜并打印路径)

    POJ 3414 Pots(深搜并打印路径) You are given two pots, having the volume of A and B liters respectively. The ...

最新文章

  1. json对象转为url参数_Day48_Ajaxamp;Json
  2. 如何在主机win10和虚拟机(virtualbox)中的Ubuntu进行文件传输即共享文件夹的建立
  3. 《Lancet》发表全球学者联合声明!
  4. 测量左右磁极的原片磁铁
  5. c语言查找功能的怎么使用方法,求C语言实现查询功能(如果选择3,如何实现查询)...
  6. Linux入门笔记——系统目录结构
  7. disruptor模拟高速处理大规模订单类业务场景
  8. 新概念51单片机C语言教程纠错(2)
  9. 地图控件快速入门——控制地图
  10. 使用免费ip代理进行投票
  11. hdu 3461 Code Lock(并查集)2010 ACM-ICPC Multi-University Training Contest(3)
  12. 学生成绩互帮互助分组C语言,C语言实现—学生成绩管理系统(Linux下运行)
  13. Kinect 数据录制与回放
  14. MATLAB与STK互联17:卫星对象操作(8)—地面站可见性计算并获取数据
  15. layer:子父之间的数据传递
  16. ultravnc 反向连接_C程序以反向显示链接列表
  17. assignin与evalin用法理解
  18. 在web网页中打开word文档
  19. ZYNQ aurora_8b10b光通信使用
  20. 【华为OD机试真题 JAVA】跳格子游戏

热门文章

  1. objective C 随机数
  2. Point to Raster 工作原理
  3. 5000字 大数据时代读书笔记_大数据读书笔记3000字
  4. python视频教程唐学韬-《吐血整理》-顶级程序员书单集
  5. javaweb+vue汽车4S店车辆维修管理系统springboot
  6. QT编写的数据转曲线工具
  7. 流体力学有限元法(二)
  8. CrossApp推出移动应用开发神器CrossApp Style
  9. zoom下载官网android最新,Zoom手机版app下载安装包-Zoom手机版安卓软件下载v5.0-后壳下载...
  10. 数字电路:数据选择器与译码器