迷宫的路径

问题描述

给定一个迷宫,这个迷宫一定存在一条从起点到终点的路径,且起点和终点一定在迷宫的边缘且不在拐角,起点和终点不相邻。

根据迷宫的特性,如果选择左边或右边的墙并一直沿着墙走下去,就一定能走到终点。

请找出只沿着左边墙走、只沿着右边墙走走到终点的路径和到终点的最短路径。

算法思路

以沿着左墙走为例,沿着墙走的时候,判断现在走动的方向,不同的方向的“左手边”的优先顺序是不一样的,当现在是往上走过来的时候,改点的左边就是左,如果左边是墙,则优先走上面,如果上面也是墙,则走右边,如果右边是墙,则走下面(回去)。每走一步,都要更正当前走的方向,以判断哪边是左手边。

方向向右时:

左手边的顺序应为:上、右、下、左

右手边的顺序应为:下、右、上、左

方向向左时:

左手边的顺序应为:下、左、上、右

右手边的顺序应为:上、左、下、右

方向向下时:

左手边的顺序应为:右、下、左、上

右手边的顺序应为:左、下、右、上

方向向上时:

左手边的顺序应为:左、上、右、下

右手边的顺序应为:右、上、左、下

对于寻找最短路径,使用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
#.#.#.#.#
#########

运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值