题意:
有一个最多包涵9*9个交叉点的迷宫。输入起点,离开起点时的朝向和终点,求一条最短路。
思路:
这个迷宫的特殊之处在于:进入一个交叉点的方向不同,那么允许出去的方式也不同。而且朝向起到了关键的作用。所以要用一个三元组(r,c,dir)表示位于(r,c)面朝dir这个状态。由于初始时第一步怎么走是确定的,因此要从X1,Y1开始BFS,而不是X0,Y0。由于要打印路径,因此要记录前驱。
#include <queue>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
int x,y;
int w;
void init(int nx, int ny, int nw){
x = nx;
y = ny;
w = nw;
}
}p[10][10][4];
int X0,Y0,X1,Y1,W1,SX,SY;
int dir[4][3][2] ={{-1, 0, 0, -1, 0, 1},
{0, 1, -1, 0, 1, 0},
{1, 0, 0, 1, 0, -1},
{0, -1, 1, 0, -1, 0}
};///移动数组
int map[10][10][4],vis[10][10][4];
int id(char c){
if(c == 'N' || c == 'F') return 0;
else if(c == 'E' || c == 'L') return 1;
else if(c == 'S' || c == 'R') return 2;
else return 3;
}
void print(int x, int y, int w);
int bfs(int x, int y, int w){
queue <node> q;
while(!q.empty())
q.pop();
node a,b;
a.init(x, y, w);
vis[a.x][a.y][a.w] = 0;
q.push(a);
while(!q.empty()){
a = q.front();
q.pop();
if(a.x == SX && a.y == SY){
print(a.x, a.y, a.w);
return 1;
}
int xx, yy, ww;
for(int i=0; i<3; i++){
xx = a.x, yy = a.y, ww = a.w;
xx += dir[a.w][i][0];
yy += dir[a.w][i][1];
if(i == 1) ww = (ww + 3) % 4;///用数字间的关系模拟向左转
else if(i == 2) ww = (ww + 1) % 4;
b.init(xx, yy, ww);
if((map[a.x][a.y][a.w]) & (1 << i)){///a & pow(2,n)检测a的第n位是否为1,是返回正数,否则返回假
if(xx < 1 || xx > 9 || yy < 1 || yy > 9)
continue;
if(vis[xx][yy][ww] >= 0)
continue;
vis[xx][yy][ww] = vis[a.x][a.y][a.w] + 1;
p[xx][yy][ww] = a;///记录前驱即父亲节点以打印路径
q.push(b);
}
}
}
return 0;
}
void print(int x, int y, int w){///用动态数组打印路径
vector <node> v;
node a,b;
a.init(x, y, w);
v.push_back(a);
while(vis[a.x][a.y][a.w]){
a = p[a.x][a.y][a.w];
v.push_back(a);
}
a.init(X0, Y0, W1);
v.push_back(a);
int cnt = 0;
for(int i=v.size() - 1; i >=0; i--){
if(cnt % 10 == 0) cout << " ";///控制输出十列
cout << " (" << v[i].x << "," << v[i].y << ")";
if(++cnt % 10 == 0) cout << endl;
}
if(v.size() % 10) cout << endl;
}
int main(){
// freopen("in.txt", "r", stdin);
char str[30];
while(cin >> str){
if(!strcmp(str, "END")) break;
cout << str << endl;
memset(map, 0, sizeof(map));
memset(vis, -1, sizeof(vis));
char c;
cin >> X0 >> Y0 >> c >> SX >> SY;
W1 = id(c);
X1 = X0 + dir[W1][0][0];
Y1 = Y0 + dir[W1][0][1];
int xx,yy;
while(cin >> xx && xx){
cin >> yy;
gets(str);
int i = 1, j = id(str[1]);
while(str[i++] != '*'){
if(str[i] == ' '){
j = id(str[++i]);
continue;
}
map[xx][yy][j] ^= (1 << id(str[i]));///a ^ pow(2,n)是将a的第n位取反
}
}
if(!bfs(X1, Y1, W1)) cout << " No Solution Possible" << endl;
}
return 0;
}