我是靠谱客的博主 野性天空,最近开发中收集的这篇文章主要介绍Abbott的复仇(Abbott's Revenge),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目链接:https://uva.onlinejudge.org/external/8/816.pdf

紫书:P165

题意:

有一个最多包含9*9个交叉点的迷宫。输入起点、离开起点时的朝向和终点,求一条最短路(多解时任意输出一个即可)。

 

【分析】

       利用队列实现广度搜索BFS来遍历图寻找最短路径。

       用一个三元组(r, c, dir)表示“位于(r, c),面朝dir”这个状态。假设入口位置为(r0, c0),朝向为dir,则初始状态并不是(r0, c0, dir),而是(r1, c1, dir),其中,(r1, c1)是(r0, c0)沿着方向dir走一步之后的坐标。此处用d[r][c][dir]表示初始状态到(r, c, dir)的最短路长度,并且用p[r][c][dir]保存了状态(r, c, dir)在BFS树中的父结点。

       在输入过程中,读取r0,c0,dir,并且计算出r1,c1即初始状态位置,读取终点位置r2,c2。读取交叉点的位置允许出去的方向,将朝向 dir 和转弯方向 turn 转化为编号0~3和0~2,并储存在has_edge数组中,其中has_edge[r][c][dir][turn]表示当前状态是(r, c, dir),是否可以沿着转弯方向turn行走。在BFS遍历的过程中,可以依据has_edge[r][c][dir][turn]判断位置(r, c, dir)是否可以这样转弯走到新状态。

#include <bits/stdc++.h>
using namespace std;
struct Node
{
int r,c,dir;
Node (int r=0,int c=0,int dir = 0) : r(r),c(c),dir(dir) {}
};
const int Maxn = 10;
const char* dirs = "NESW";
const char* turns = "FLR";
int dir_id(char c)
{
return strchr(dirs,c) - dirs;
}
int turn_id(int c)
{
return strchr(turns,c) - turns;
}
const int dr[] = {-1,0,1,0};
const int dc[] = {0,1,0,-1};
Node walk(const Node& u,int turn)
{
int dir = u.dir;
if(turn==1) dir = (dir - 1 + 4)%4;
///向左转
if(turn==2) dir = (dir+ 1)%4;
///向右转
return Node(u.r+dr[dir],u.c+dc[dir],dir);
}
bool inside(int r,int c)
{
if(r>=1&&r<=9&&c>=1&&c<=9)
return true;
else return false;
}
int has_edge[Maxn][Maxn][4][3];
int r0,c0,r1,c1,r2,c2,dir;
bool read()
{
char s[99],s2[99];
if(scanf("%s%d%d%s%d%d",s,&r0,&c0,s2,&r2,&c2)!=6) return false;
puts(s);
dir = dir_id(s2[0]);
r1 = r0 + dr[dir];
c1 = c0 + dc[dir];
memset(has_edge,0,sizeof(has_edge));
for(;;)
{
int r,c;
scanf("%d",&r);
if(r==0) break;
scanf("%d",&c);
while(scanf("%s",s)==1&&s[0]!='*')
{
for(int i=1; i<strlen(s); i++)
{
has_edge[r][c][dir_id(s[0])][turn_id(s[i])] = 1;
}
}
}
return true;
}
int d[Maxn][Maxn][4];
Node p[Maxn][Maxn][4];
void print_ans (Node u)
{
vector<Node> nodes;
for(;;)
{
nodes.push_back(u);
if(d[u.r][u.c][u.dir]==0) break;
u = p[u.r][u.c][u.dir];
}
nodes.push_back(Node(r0,c0,dir));
int cnt = 0;
for(int i=nodes.size()-1; i>=0; i--)
{
if(cnt%10==0) printf(" ");
printf(" (%d,%d)",nodes[i].r,nodes[i].c);
cnt++;
if(cnt%10==0) printf("n");
}
if(nodes.size()%10!=0) puts("");
}
void bfs()
{
queue<Node> q;
memset(d, -1, sizeof(d));
Node u(r1, c1, dir);
d[u.r][u.c][u.dir] = 0;
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 = 0; i < 3; 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] < 0)
{
d[v.r][v.c][v.dir] = d[u.r][u.c][u.dir] + 1;
p[v.r][v.c][v.dir] = u;
q.push(v);
}
}
}
printf("
No Solution Possiblen");
}
int main()
{
while(read())
{
bfs();
}
return 0;
}

最后

以上就是野性天空为你收集整理的Abbott的复仇(Abbott's Revenge)的全部内容,希望文章能够帮你解决Abbott的复仇(Abbott's Revenge)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部