题意:一个9*9的迷宫,迷宫上的每个位置有不同的转弯方式,当你从不同的方向走到每个位置时有不同的转弯方式,最后求到目的地的最短路径的过程!
思路:
输入需要处理:按题意输入,但是将坐标,方向和转弯方式要存放has_edge[x][y][dir][turn]的下表,将此位置置为1说明此位置有路!
进行dfs计算最短路:每出队一个点,将它的3个转弯方式计算下下个状态,看看有没有,计算下一个状态时:要考虑转弯不同方向会变:F正常,L逆时针,R顺时针!
输出处理:将最后一个状态开始,倒着存入vector中,每次利用p[r][c][dir](bfs时存放每次的根节点)获取上一次的根节点!最后倒的输出即可!
参考:入门经典-例题6-14-P166 + 点击打开链接
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 10;
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,dir;
Node(){};
Node(int rr,int cc,int ddir){
r = rr;c = cc;dir = ddir;
}
} ;
int dir_id(char c){return strchr(dirs,c) - dirs;}//计算方向,因为strchr返回指针位置,而dirs也定义的指针,所以相减可得方向位置
int turn_id(char c){return strchr(turns,c) - turns;}//同上
int sr,sc,er,ec,dir,r0,c0;
int has_edge[maxn][maxn][maxn][maxn];//存放输入的位置
int d[maxn][maxn][maxn];//表示初始状态到(r,c,dir)的最短路长度
Node p[maxn][maxn][maxn];//保存状态(r,c,dir)在BFS树的父节点
bool inside(int x,int y){
if(x > 0 && x < 10 && y > 0 && y < 10) return true;
return false;}
Node walk(const Node& u,int turn){//行走的状态和转弯方式,计算出后续状态
int dir = u.dir;
if(turn == 1) dir = (dir + 3) % 4;//逆时针,向左
if(turn == 2) dir = (dir + 1) % 4;//顺时针,向右
return Node(u.r + dr[dir],u.c + dc[dir] , dir);}//返回后续状态
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);
if(++cnt % 10 == 0) printf("\n");
}
if(nodes.size() % 10 != 0) printf("\n");
}
void solve_bfs(){//bfs寻找最短路
queue<Node>q;
memset(d,-1,sizeof(d));
Node u(sr,sc,dir);
d[u.r][u.c][u.dir] = 0;
q.push(u);
while(!q.empty()){
Node u = q.front();q.pop();
if(u.r == er && u.c == ec){ 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 Possible\n");//无解
return;}
int main(){
string name;
char dir_str[20];
int x,y;
while(cin >> name && name != "END"){
memset(has_edge,0,sizeof(has_edge));
cout << name<< endl;
scanf("%d%d%s%d%d",&r0,&c0,dir_str,&er,&ec);
dir = dir_id(dir_str[0]);
sr = r0 + dr[dir];sc = c0 + dc[dir];
while(scanf("%d",&x) && x){
scanf("%d",&y);
while(scanf("%s",dir_str) && dir_str[0] != '*'){
int sdir = dir_id(dir_str[0]);//计算当前方向
for(int i=1;dir_str[i] != '\0';i++){
int turn = turn_id(dir_str[i]);//计算当前转弯方式
has_edge[x][y][sdir][turn] = 1;//此位置存在点的方向和转弯,标记为1
}
}
}
solve_bfs();//bfs求解
}
return 0;}