UVA 816 -- Abbott's Revenge(BFS求最短路)

  有一个 9 * 9 的交叉点的迷宫。 输入起点, 离开起点时的朝向和终点, 求最短路(多解时任意一个输出即可)。进入一个交叉点的方向(用NEWS表示不同方向)不同时, 允许出去的方向也不相同。 例如:1 2 WLF NR ER * 表示如果 进去时朝W(左), 可以 左转(L)或直行(F), 如果 朝N只能右转(R) 如果朝E也只能右转。* 表示这个点的描述结束啦!

  输入有: 起点的坐标, 朝向, 终点的坐标。然后是各个坐标,和各个坐标点的情况(进去方向和可以出去的方向) 以*号表示各个坐标点描述的结束。

  题目分析:本题和普通的迷宫在本质上是一样的, 但是由于“朝向”也起了关键的作用, 所以需要一个三元组(r,c, dir)表示位于(r, c)面朝dir 的状态。 假设入口位置为(r0,c0)朝向为dir , 则初始状态并不是(r0, c0, dir), 而是(r1, c1, dir)因为开始时他别无选择, 只有一个规定的方向。 其中, (r1, c1)是沿着方向dir走一步之后的坐标, dir刚好是他进入该点时的朝向。    此处用d[r][c][dir]表示初始状态到(r, c, dir)的最短路长度, 并且用 p[r][c][dir]保存了状态(r, c, dir)在BFS树中的父结点。

规律:: 很多复杂的迷宫问题都可以转化成最短路问题, 然后用BFS求解。 在套用BFS框架之前, 需要先搞清楚图中的“结点”包含哪些内容。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
int r0,c0,r2,c2,r1,c1,dir;
const char *dirs = "NESW";
const char *turns = "FLR";
const int dr[] = {-,,,};
const int dc[] = {,,,-};
const int maxn = ;
int dir_id(char s){return strchr(dirs,s) - dirs;}
int turn_id(char s){return strchr(turns,s) - turns;}
int has_edge[maxn][maxn][][];// 表示当前状态(r,c,dir),是否可以沿着转弯方向[trun]行走。
struct Node{
int r,c,dir;
Node(int r=,int c=,int dir=):r(r),c(c),dir(dir) {}
};
int d[maxn][maxn][];///表示初始状态到(r,c,dir)的最短路径长度
Node p[maxn][maxn][];///用来记录从哪一步走到(r,c,dir),即其父节点
///读入地图
bool read_input()
{
char s[],s2[];
if(scanf("%s%d%d%s%d%d",s,&r0,&c0,s2,&r2,&c2) != ) return false;
cout<<s<<endl;
dir = dir_id(s2[]);
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;
while(cin>>s && s[] != '*')
{
for(int i=;i<strlen(s);i++)///将当前路口(r,c),可以的前进方向存到has_edge中
has_edge[r][c][dir_id(s[])][turn_id(s[i])] = ;
}
}
return true;
}
///从当前节点u,转向为i,前进一步
Node walk(Node u,int i)
{
int temp = u.dir;
if(i == ) temp = (temp+)%;///逆时针旋转,L
if(i == ) temp = (temp+)%;///顺时针旋转,R
return Node(u.r + dr[temp],u.c + dc[temp],temp);
}
///判断是否出界
bool inside(int r,int c)
{
return r >= && r <= && c >= && c <= ;
}
///将结果进行打印
void print_ans(Node u)
{
vector<Node> nodes;
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));
///打印解,每行10个
int cnt = ;
for(int i=nodes.size()-;i>=;i--)
{
if(cnt % == ) printf(" ");
printf(" (%d,%d)",nodes[i].r,nodes[i].c);
if(++cnt % == ) cout<<endl;
}
if(nodes.size() % != ) cout<<endl;
}
///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) {print_ans(u);return;}///到达终点
for(int i=;i<;i++)///3个方向,0-F,1-L,2-R
{
Node v = walk(u,i);//超当前方向走,下一个结点
if(has_edge[u.r][u.c][u.dir][i] ///1.判断是否能向当前方向走
&& inside(v.r,v.c)///2.判断是否出界
&& d[v.r][v.c][v.dir] < )///3.判断是否已经走过这条路 u->v
{
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);
}
}
}
cout<<" No Solution Possible"<<endl;//走了所有可以走的可能, 无法到达终点
}
int main()
{
while(read_input())
{
solve();
} return ;
}

UVA 816 -- Abbott's Revenge(BFS求最短路)的更多相关文章

  1. Uva 816 Abbott's Revenge(BFS)

    #include<cstdio> #include<cstring> #include<vector> #include<queue> using na ...

  2. UVA 816 Abbott’s Revenge

    bfs求最短路,递归打印最短路的具体路径: 难点: 当前状态和转弯方式很复杂,要仔细处理: 递归打印:用一个数组存储路径中结点的前一个节点,递归查找 (bfs无法确定下一个结点,但对于没一个结点,它的 ...

  3. Uva - 816 - Abbott's Revenge

    这个迷宫问题还是挺好玩的,多加了一个转向的问题,有些路口不同的进入方式会有不同的转向限制,这个会比较麻烦一点,所以定义结点结构体的时候需要加一个朝向dir.总体来说是一道BFS求最短路的问题.最后打印 ...

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

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

  5. uva 816 abbott's revenge ——yhx

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAncAAAN5CAYAAABqtx2mAAAgAElEQVR4nOy9sY4jydKezVuoayhH0r

  6. UVA 816 Abbott's Revenge 紫书

    紫书的这道题, 作者说是很重要. 但看着题解好长, 加上那段时间有别的事, 磨了几天没有动手. 最后,这道题我打了五遍以上 ,有两次被BUG卡了,找了很久才找到. 思路紫书上有,就缺少输入和边界判断两 ...

  7. UVA 816 - Abbott&#39;s Revenge(BFS)

    UVA 816 - Abbott's Revenge option=com_onlinejudge&Itemid=8&page=show_problem&category=59 ...

  8. 图-用DFS求连通块- UVa 1103和用BFS求最短路-UVa816。

    这道题目甚长, 代码也是甚长, 但是思路却不是太难.然而有好多代码实现的细节, 确是十分的巧妙. 对代码阅读能力, 代码理解能力, 代码实现能力, 代码实现技巧, DFS方法都大有裨益, 敬请有兴趣者 ...

  9. UVa 816 (BFS求最短路)

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

随机推荐

  1. vue路由(基于VScode开发)

    index.js如果在router目录下,代表这个js文件只是路由使用 main.js中为全局,需要引入使用到的组件,一般vue中不用写东西vue中el挂载哪个就哪个组件为根目录,传值数据绑定的时候在 ...

  2. 配置maven的国内镜像

    pom.xml文件出现错误标记,一般是相关的maven资源没有下载完整. 1,配置maven的国内镜像,保证能够顺利下载maven中配置的资源. 在maven的配置文件  settings.xml  ...

  3. linux shell 数组的使用

    引言 在Linux平台上工作,我们经常需要使用shell来编写一些有用.有意义的脚本程序.有时,会经常使用shell数组.那么,shell中的数组是怎么表现的呢,又是怎么定义的呢?接下来逐一的进行讲解 ...

  4. 02-springmvc分布式项目dataService项目配置

    spring总文件 文件名:applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> ...

  5. mysql语句修改zencart产品原价为特价的倍数

    mysql语句修改zencart产品原价为特价的倍数,下面语句将原价设为特价的3倍: ; ;

  6. win redis安装

    一.下载windows版本的Redis 去官网找了很久,发现原来在官网上可以下载的windows版本的,现在官网以及没有下载地址,只能在github上下载,官网只提供linux版本的下载 官网下载地址 ...

  7. 安全框架Shiro和SpringSecurity的比较

    来自:https://www.cnblogs.com/zoli/p/11236799.html 两个基本的概念 安全实体:系统需要保护的具体对象数据 权限:系统相关的功能操作,例如基本的CRUD Sh ...

  8. nginx第六天

    nginx正向代理 反向代理 Nginx正向代理配置 Nginx正向代理使用场景并不多见. 需求场景1: 如果在机房中,只有一台机器可以联网,其他机器只有内网,内网的机器想用使用yum安装软件包,在能 ...

  9. linux负载均衡杂谈

    假如架构中的主机拥有全量数据集,即使其中一台挂了,也不会导致离线,高可用(负载均衡集群) 假如架构中的各主机只拥有sharing,那我们谓之 分布式集群 硬件ctrix F5-BIG-IP(一台动辄2 ...

  10. Phaserjs V2的state状态解析及技巧

    用phaserjs开发了好多游戏了,但是对phaser还是了解不深,只知道怎么去用,今天就特意花点时间研究下phaser的状态管理到底是怎么回事. 首先,new Phaser.Game,以下是Phas ...