这个题是一个很经典的BFS求图最短路的问题,复杂一点的就是加了个朝向。这个题细节很多而且输出格式巨坑。贴AC代码,解释都在注释里
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10;
int d[maxn][maxn][4]; // 记录初始状态到这时的长度,三个值分别为横、纵坐标、朝向
string name; //迷宫名字
int has_edge[maxn][maxn][4][4]; //记录某个点可以往什么方向走
const char *dirs = "NESW";
const char *turns = "FLR";
// 这个题真的麻烦
// 方便判断每一次行走后新的点的位置
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
// 构造一个结构体来存点
struct Node
{
int r,c,d;
Node(int r_=0,int c_=0,int d_=0){
r=r_;
c=c_;
d=d_;
};
Node& operator=(const Node & cp) {
this->r = cp.r;
this->c = cp.c;
this->d = cp.d;
return *this;
}
};
Node startPoint,nowPoint,desPoint; // 起始点、现在所在点、目的点
Node p[maxn][maxn][4]; // 记录父节点,方便回溯输出路径
int dir_id(char c)
{
return strchr(dirs, c) - dirs;
}
int turns_id(char c) {
return strchr(turns, c) - turns;
}
// 输入函数
bool input()
{
memset(has_edge,0,sizeof(has_edge));
cin>>name;
if(name=="END")
return false;
char tmpd;
cin>>startPoint.r>>startPoint.c>>tmpd>>desPoint.r>>desPoint.c;
nowPoint.d = dir_id(tmpd); // 注意是当前点而不是初始点
// 下面两行代码可能有点难理解,多思考一下
// 面朝南方则行加一,面朝北方则行减一,面朝东或西则行数不变
// 因为刚开始的时候只能朝当前方向直行,所以可以这么写
nowPoint.r = startPoint.r + dr[nowPoint.d];
nowPoint.c = startPoint.c + dc[nowPoint.d];
int tmpr,tmpc;
string s;
while(cin>>tmpr && tmpr) {
cin>>tmpc;
while(cin>>s&&s!="*") {
for(int i = 1; i < s.length(); i++)
has_edge[tmpr][tmpc][dir_id(s[0])][turns_id(s[i])] = 1; // 本质上就是构图
}
}
return true;
};
// 万里长征走完第一步了,输入函数写完了
// 接下来写走路的函数
Node walk(const Node &present, int turn) {
int dic = present.d;
// turn为0是直行,所以方向不改变
if(turn==1)//左转
dic = (dic+3)%4;
if(turn==2)
dic = (dic+1)%4;
return Node(present.r+dr[dic],present.c+dc[dic],dic);
};
// 判断是否在图内
bool inside(int r, int c) {
return r > 0 && c > 0 && r < maxn && c < maxn;
};
// 输出函数他来了
void print_ans(Node&u)
{
stack<Node> arr;
while(true) {
arr.push(u);
if(d[u.r][u.c][u.d]==0)
break;
u = p[u.r][u.c][u.d];
}
arr.push(startPoint); // 千万别忘记初始点
int cnt = 0;
int s = arr.size();
while(!arr.empty()) {
Node tmp = arr.top();
arr.pop();
if(cnt%10==0)
cout<<" ";
else
cout<<" ";
cout<<"("<<tmp.r<<","<<tmp.c<<")";
cnt++;
if(cnt%10==0)
cout<<endl;
}
if(s % 10 !=0)
cout<<endl;
};
void solve()
{
queue<Node> q;
cout<<name<<endl;
memset(d,-1,sizeof(d)); // 记得清空
Node u = nowPoint; // 要记得刚开始的时候,现在的点不是初始点,而是初始点朝前走的一个点
d[u.r][u.c][u.d]=0; // 想清楚为什么是这里为0
q.push(u);
while(!q.empty()) {
u = q.front();
q.pop();
if(u.r==desPoint.r&&u.c==desPoint.c) {
print_ans(u);
return;
}
for(int i = 0; i<3; i++) { // 看三个方向哪个可以走
Node v = walk(u,i);
if(has_edge[u.r][u.c][u.d][i]&&inside(v.r,v.c)&&d[v.r][v.c][v.d]==-1) {
d[v.r][v.c][v.d] = d[u.r][u.c][u.d] + 1;
p[v.r][v.c][v.d] = u;
q.push(v);
}
}
}
cout << " No Solution Possible" << endl; // 前面有两个空格,坑的一批
return;
};
int main()
{
while(input())
solve();
return 0;
}