概述
题目链接: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)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复