问题描述
给定一个迷宫,这个迷宫一定存在一条从起点到终点的路径,且起点和终点一定在迷宫的边缘且不在拐角,起点和终点不相邻。
根据迷宫的特性,如果选择左边或右边的墙并一直沿着墙走下去,就一定能走到终点。
请找出只沿着左边墙走、只沿着右边墙走走到终点的路径和到终点的最短路径。
算法思路
以沿着左墙走为例,沿着墙走的时候,判断现在走动的方向,不同的方向的“左手边”的优先顺序是不一样的,当现在是往上走过来的时候,改点的左边就是左,如果左边是墙,则优先走上面,如果上面也是墙,则走右边,如果右边是墙,则走下面(回去)。每走一步,都要更正当前走的方向,以判断哪边是左手边。
方向向右时:
左手边的顺序应为:上、右、下、左
右手边的顺序应为:下、右、上、左
方向向左时:
左手边的顺序应为:下、左、上、右
右手边的顺序应为:上、左、下、右
方向向下时:
左手边的顺序应为:右、下、左、上
右手边的顺序应为:左、下、右、上
方向向上时:
左手边的顺序应为:左、上、右、下
右手边的顺序应为:右、上、左、下
对于寻找最短路径,使用bfs寻找即可。
代码实现
#include <iostream>
using namespace std;
char maze[40][40];
const int M = 999;
int dir[4][2] = { {0,1},{0,-1},{1,0},{-1,0} }; //right, left, down, up
int left_right[4][2] = { {-1,0},{0,1},{1,0},{0,-1} }; //up, right, down, left
int left_left[4][2] = { {1,0},{0,-1},{-1,0},{0,1} }; //down, left, up, right
int left_down[4][2] = { {0,1},{1,0},{0,-1},{-1,0} }; //right, down, left, up
int left_up[4][2] = { {0,-1},{-1,0},{0,1},{1,0} }; //left, up, right, down
int right_right[4][2] = { {1,0},{0,1},{-1,0},{0,-1} }; //down, right, up, left
int right_left[4][2] = { {-1,0},{0,-1},{1,0},{0,1} }; //up, left, down, right
int right_down[4][2] = { {0,-1},{1,0},{0,1},{-1,0} }; //left, down, right, up
int right_up[4][2] = { {0,1},{-1,0},{0,-1},{1,0} }; //right, up, left, down
int flag;
int endnumber;
int lstep = 1;
int rstep = 1;
int mstep = 1;
int answer[3];
int start_x;
int start_y;
struct record
{
int x;
int y;
int step;
};
typedef struct QueNode
{
record data[M];
int front, rear;
}*SeQue;
SeQue S;
void init()
{
S->front = S->rear = 0;
}
bool empty()
{
if (S->front == S->rear)
return true;
else
return false;
}
void push(record val)
{
S->data[S->rear] = val;
S->rear = (S->rear + 1) % M;
}
void pop()
{
S->front = (S->front + 1) % M;
}
void left(int i, int x, int y)
{
if (endnumber > 0)
{
return;
}
//0:right, 1:left, 2:down, 3:up
lstep++;
int new_pos_x;
int new_pos_y;
if (i == 0) //right
{
//0:up, 1:right, 2:down, 3:left
for (int j = 0; j < 4 && endnumber == 0; j++)
{
new_pos_x = x + left_right[j][0];
new_pos_y = y + left_right[j][1];
if (maze[new_pos_x][new_pos_y] == 'E')
{
endnumber++;
lstep++;
}
if (maze[new_pos_x][new_pos_y] == '#')
continue;
if (maze[new_pos_x][new_pos_y] == '.')
{
if (j == 0)
flag = 3;
if (j == 1)
flag = 0;
if (j == 2)
flag = 2;
if (j == 3)
flag = 1;
left(flag, new_pos_x, new_pos_y);
}
}
}
if (i == 1) //left
{
//0:down, 1:left, 2:up, 3:right
for (int j = 0; j < 4 && endnumber == 0; j++)
{
new_pos_x = x + left_left[j][0];
new_pos_y = y + left_left[j][1];
if (maze[new_pos_x][new_pos_y] == 'E')
{
lstep++;
endnumber++;
}
if (maze[new_pos_x][new_pos_y] == '#')
continue;
if (maze[new_pos_x][new_pos_y] == '.')
{
if (j == 0)
flag = 2;
if (j == 1)
flag = 1;
if (j == 2)
flag = 3;
if (j == 3)
flag = 0;
left(flag, new_pos_x, new_pos_y);
}
}
}
if (i == 2) //down
{
//0:right, 1:down, 2:left, 3:up
for (int j = 0; j < 4 && endnumber == 0; j++)
{
new_pos_x = x + left_down[j][0];
new_pos_y = y + left_down[j][1];
if (maze[new_pos_x][new_pos_y] == 'E')
{
lstep++;
endnumber++;
break;
}
if (maze[new_pos_x][new_pos_y] == '#')
continue;
if (maze[new_pos_x][new_pos_y] == '.')
{
if (j == 0)
flag = 0;
if (j == 1)
flag = 2;
if (j == 2)
flag = 1;
if (j == 3)
flag = 3;
left(flag, new_pos_x, new_pos_y);
}
}
}
if (i == 3) //up
{
//0:left, 1:up, 2:right, 3:down
for (int j = 0; j < 4 && endnumber == 0; j++)
{
new_pos_x = x + left_up[j][0];
new_pos_y = y + left_up[j][1];
if (maze[new_pos_x][new_pos_y] == 'E')
{
lstep++;
endnumber++;
}
if (maze[new_pos_x][new_pos_y] == '#')
continue;
if (maze[new_pos_x][new_pos_y] == '.')
{
if (j == 0)
flag = 1;
if (j == 1)
flag = 3;
if (j == 2)
flag = 0;
if (j == 3)
flag = 2;
left(flag, new_pos_x, new_pos_y);
}
}
}
}
void right(int i, int x, int y)
{
if (endnumber > 0)
return;
//0:right, 1:left, 2:down, 3:up
rstep++;
int new_pos_x;
int new_pos_y;
if (i == 0) //right
{
//0:down, 1:right, 2:up, 3:left
for (int j = 0; j < 4 && endnumber == 0; j++)
{
new_pos_x = x + right_right[j][0];
new_pos_y = y + right_right[j][1];
if (maze[new_pos_x][new_pos_y] == 'E')
{
endnumber++;
rstep++;
}
if (maze[new_pos_x][new_pos_y] == '#')
continue;
if (maze[new_pos_x][new_pos_y] == '.')
{
if (j == 0)
flag = 2;
if (j == 1)
flag = 0;
if (j == 2)
flag = 3;
if (j == 3)
flag = 1;
right(flag, new_pos_x, new_pos_y);
}
}
}
if (i == 1) //left
{
//0:up, 1:left, 2:down, 3:right
for (int j = 0; j < 4 && endnumber == 0; j++)
{
new_pos_x = x + right_left[j][0];
new_pos_y = y + right_left[j][1];
if (maze[new_pos_x][new_pos_y] == 'E')
{
rstep++;
endnumber++;
}
if (maze[new_pos_x][new_pos_y] == '#')
continue;
if (maze[new_pos_x][new_pos_y] == '.')
{
if (j == 0)
flag = 3;
if (j == 1)
flag = 1;
if (j == 2)
flag = 2;
if (j == 3)
flag = 0;
right(flag, new_pos_x, new_pos_y);
}
}
}
if (i == 2) //down
{
//0:left, 1:down, 2:right, 3:up
for (int j = 0; j < 4 && endnumber == 0; j++)
{
new_pos_x = x + right_down[j][0];
new_pos_y = y + right_down[j][1];
if (maze[new_pos_x][new_pos_y] == 'E')
{
rstep++;
endnumber++;
break;
}
if (maze[new_pos_x][new_pos_y] == '#')
continue;
if (maze[new_pos_x][new_pos_y] == '.')
{
if (j == 0)
flag = 1;
if (j == 1)
flag = 2;
if (j == 2)
flag = 0;
if (j == 3)
flag = 3;
right(flag, new_pos_x, new_pos_y);
}
}
}
if (i == 3) //up
{
//0:right, 1:up, 2:left, 3:down
for (int j = 0; j < 4 && endnumber == 0; j++)
{
new_pos_x = x + right_up[j][0];
new_pos_y = y + right_up[j][1];
if (maze[new_pos_x][new_pos_y] == 'E')
{
rstep++;
endnumber++;
}
if (maze[new_pos_x][new_pos_y] == '#')
continue;
if (maze[new_pos_x][new_pos_y] == '.')
{
if (j == 0)
flag = 0;
if (j == 1)
flag = 3;
if (j == 2)
flag = 1;
if (j == 3)
flag = 2;
right(flag, new_pos_x, new_pos_y);
}
}
}
}
void bfs()
{
record pos{};
record newpos{};
while (!empty())
{
pos.x = S->data[S->front].x;
pos.y = S->data[S->front].y;
pos.step = S->data[S->front].step;
pop();
if (endnumber > 0)
continue;
for (int i = 0; i < 4 && endnumber == 0; i++)
{
newpos.x = pos.x + dir[i][0];
newpos.y = pos.y + dir[i][1];
if (maze[newpos.x][newpos.y] == 'E')
{
newpos.step = pos.step + 1;
mstep = newpos.step;
endnumber++;
}
if (maze[newpos.x][newpos.y] == '#')
continue;
if (maze[newpos.x][newpos.y] == '.')
{
newpos.step = pos.step + 1;
push(newpos);
}
}
}
}
int main()
{
int T;
int W, H;
cout << "please input the number of maze" << endl;
cin >> T;
for (int i = 0; i < T; i++)
{
cout << "please input the width and the height of the maze" << endl;
cin >> W >> H;
for (int j = 0; j < H; j++)
{
for (int k = 0; k < W; k++)
{
cin >> maze[j][k];
if (maze[j][k] == 'S')
{
start_x = j;
start_y = k;
}
}
}
//left
for (int i = 0; i < 4; i++)
{
int new_x = start_x + dir[i][0];
int new_y = start_y + dir[i][1];
if (maze[new_x][new_y] == '.')
{
left(i, new_x, new_y);
}
}
//right
endnumber = 0;
for (int i = 0; i < 4; i++)
{
int new_x = start_x + dir[i][0];
int new_y = start_y + dir[i][1];
if (maze[new_x][new_y] == '.')
{
right(i, new_x, new_y);
}
}
//min
endnumber = 0;
S = new QueNode;
init();
record start{};
start.x = start_x;
start.y = start_y;
start.step = 1;
push(start);
bfs();
//output
cout << "lstep: " << lstep << " rstep: " << rstep << " mstep: " << mstep << endl;
for (int i = 0; i < 40; i++)
for (int j = 0; j < 40; j++)
maze[i][j] = ' ';
endnumber = 0;
lstep = 1;
rstep = 1;
mstep = 1;
}
}
测试用例
2
8 8
########
#......#
#.####.#
#.####.#
#.####.#
#.####.#
#...#..#
#S#E####
9 5
#########
#.#.#.#.#
S.......E
#.#.#.#.#
#########