Problem Description
给你起点,给你起点的方向,给你终点,让你求起点到终点的最短路径。它会给出很多个点,告诉你在这个点你只能怎么走,”NEWS”分别对应北东南西,也就是上右下左,”FLR”分别代表直走 左转 右转。所以假如一个路口给你 “WLF”就代表如果你进来的时候朝下,你就只能左转或者直走。
代码:复杂点就多了 转弯方向的问题而已,理解了也不难。当前的方向,怎么转朝哪,都转换成整数存起来。这样好判断
#include<bits/stdc++.h>
using namespace std;
struct node
{
int r, c, dir;
};
int vis[15][15][4];//标记是否走过
node Pre[15][15][4];//记录路径
int has_edge[15][15][4][3];//判断能否走
int dr[5] = {-1, 0, 1, 0}; //上右下左
int dc[5] = {0, 1, 0, -1};
char dirs[5] = {"NESW"};//上右下左 0123
char turns[4] = {"FLR"};//直走,左转,右转 0,1,2
char s[30], s1[30];//最开始输入的字符串,中间过程输入的字符串
int r0, c0, rr, cc, r1, c1, dir1, rx, cx;//起始点,终点,起始点的下一步的点,其他点,
int dir_id(char c) {return strchr(dirs, c) - dirs;}//求当前方向对应的下标
int turn_id(char c) {return strchr(turns, c) - turns;}//求怎么转的下标
node walk(node u, int i)
{
int dir = u.dir;
if(i == 1) dir = (dir + 3) % 4;//左转
if(i == 2) dir = (dir + 1) % 4;//右转
return (node){u.r + dr[dir], u.c + dc[dir], dir};
}
void print_ans(node u)
{
vector<node> a;
for(;;)
{
a.push_back(u);//存入数组
if(vis[u.r][u.c][u.dir] == 0) break;
u = Pre[u.r][u.c][u.dir];
}
printf("%s\n", s);//输出
printf(" (%d,%d)", r0, c0);
int cnt = 1;
for(int i = a.size() - 1; i >= 0; i--)
{
if(cnt % 10 == 0) printf("\n ");
else printf(" ");
printf("(%d,%d)", a[i].r, a[i].c);
cnt++;
}
printf("\n");
}
void bfs()
{
queue<node> q;
memset(vis, 0, sizeof(vis));//初始化
q.push((node){r1, c1, dir1});//存入起始点的下一个点
while(!q.empty())
{
node u = q.front();
q.pop();
if(u.r == rr && u.c == cc) {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] && !vis[v.r][v.c][v.dir])//判断能否走
{
vis[v.r][v.c][v.dir] = vis[u.r][u.c][u.dir] + 1;//标记走过的点
Pre[v.r][v.c][v.dir] = u;//记录路径保存上一个点
q.push((node){v.r, v.c, v.dir});//存入
}
}
}
printf("%s\n", s);//找不到终点
printf(" No Solution Possible\n");
}
int main()
{
while(~scanf("%s", s))
{
if(strcmp(s, "END") == 0) break;//结束退出循环
scanf("%d %d %s %d %d", &r0, &c0, s1, &rr, &cc);
memset(has_edge, 0, sizeof(has_edge));
dir1 = dir_id(s1[0]);//求起始点的下一个点
r1 = r0 + dr[dir1];
c1 = c0 + dc[dir1];
for(;;)
{
scanf("%d", &rx);
if(!rx) break;//如果是0退出循环
scanf("%d", &cx);
while(~scanf("%s", s1))
{
if(s1[0] == '*') break;//退出循环
for(int i = 1; i < strlen(s1); i++)//存入,后面判断能否走
{
has_edge[rx][cx][dir_id(s1[0])][turn_id(s1[i])] = 1;//分别对应行,列下标,方向,如何转,能走标记1
}
}
}
bfs();
}
return 0;
}