【数据结构】用回溯法求解迷宫问题

今天呢,让我们来用栈求解一下数据结构中的著名问题---迷宫问题

我们先“制造”一个迷宫,把它放在Maze.txt文件中

Maze.txt

1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1
1 1 0 1 0 0 0 0 1 1
1 1 0 1 0 1 1 0 1 1
1 1 0 1 1 1 1 1 1 1
1 1 0 0 0 0 0 0 1 1
1 1 0 1 1 1 1 0 1 1
1 1 0 1 1 1 1 0 1 1
1 1 0 1 1 1 1 0 1 1	

其中呢,0代表可以走的路,而1呢,则代表的是不可以走的路(墙)

首先呢,我们先来定义一个结构体,用来存储坐标

struct Pos
{
	size_t _row;//行
	size_t _col;//列
};

接下来呢,我们需要从Maze.txt读入迷宫

void GetMaze(int *maze, size_t N)
{
	FILE *fp = fopen("1.txt","r");
	if (fp == NULL)
	{
		throw invalid_argument("Read maze filed");
	}
	for (size_t i = 0; i < N; ++i)
	{
		for (size_t j = 0; j < N;)
		{	
			char ch = fgetc(fp);
			if (ch == '0' || ch == '1')
			{	
				maze[i*N + j] = ch - '0';
				++j;
			}
			else if (ch == EOF)
			{
				throw invalid_argument("Maze Error");
			}
		}
	}
}

然后为了方便,我们制定一个函数,用来判断这一步是不是可以走

就是判断这个位置是不是0

bool CheckIsAccess(int *maze, size_t N, Pos next)
{
	if (maze[next._row*N + next._col] == 0)
	{
		return true;
	}
	return false;
}

利用非递归的方式求解

 
bool GetMazePath(int *maze, size_t n, Pos entry, stack&path)
{
	maze[entry._row*N + entry._col] = 2;
	Pos cur,next;
	cur = entry;
	path.push(entry);
	while (!path.empty())
	{
		cur = path.top();

		if (cur._row == N - 1)
		{
			return true;
		}

		next = cur;

		next._row += 1;
		if (CheckIsAccess((int*)maze, N, next) == true)
		{
			path.push(next);
			maze[next._row*N + next._col] = 2;
			continue;
		}
		next = cur;

		next._row -= 1;
		if (CheckIsAccess((int*)maze, N, next) == true)
		{
			path.push(next);
			maze[next._row*N + next._col] = 2;
			continue;
		}
		next = cur;

		next._col += 1;
		if (CheckIsAccess((int*)maze, N, next) == true)
		{
			path.push(next);
			maze[next._row*N + next._col] = 2;
			continue;
		}
		next = cur;

		next._col -= 1;
		if (CheckIsAccess((int*)maze, N, next) == true)
		{
			path.push(next);
			maze[next._row*N + next._col] = 2;
			continue;
		}
		next = cur;

		path.pop();
	}
	return false;
}

利用递归的方式求解

void GetMazePath_R(int *maze, size_t N, Pos entry, stack&path)
{
	if (entry._row == N - 1)
	{
		return;
	}
	Pos cur,next;
	cur = entry;

	next = cur;

	next._row += 1;
	if (CheckIsAccess((int*)maze,N,next) ==  true)
	{
		path.push(next);
		maze[next._row*N + next._col] = 2;
		GetMazePath_R(maze, N, next, path);
	}
	next = cur;

	next._row -= 1;
	if (CheckIsAccess((int*)maze, N, next) == true)
	{
		path.push(next);
		maze[next._row*N + next._col] = 2;
		GetMazePath_R(maze, N, next, path);
	}
	next = cur;

	next._col += 1;
	if (CheckIsAccess((int*)maze, N, next) == true)
	{
		path.push(next);
		maze[next._row*N + next._col] = 2;
		GetMazePath_R(maze, N, next, path);
	}
	next = cur;

	next._col -= 1;
	if (CheckIsAccess((int*)maze, N, next) == true)
	{
		path.push(next);
		maze[next._row*N + next._col] = 2;
		GetMazePath_R(maze, N, next, path);
	}
	next = cur;
}

对非递归的方法求最短路径

ReMaze表示的是重置迷宫

void ReMaze(int* maze,size_t N)
{
	for (size_t i = 0; i < N; ++i)
	{
		for (size_t j = 0; j < N; ++j)
		{
			if (maze[i*N + j] != 1)
			{
				maze[i*N + j] = 0;
			}
		}
	}
}

void TestMaze()
{
	try
	{
		int maze[N][N] = { 0 };
		int curmaze[N][N] = { 0 }; 
		GetMaze((int*)maze, N);
		stack path,MinPath,empty;
		
		while (GetMazePath((int*)maze, N, { 2, 0 }, path))
		{
			if (path.size() < MinPath.size()||MinPath.size() == 0)
			{
				MinPath = path;
			}
			ReMaze((int*)maze,N);
			maze[path.top()._row][path.top()._col] = 1;//将上次的出口改为1
			path = empty;
		}
		cout << "Min path:" << MinPath.size() << endl;
	}
	catch (exception &e)
	{
		cout << e.what() << endl;
	}
}

你可能感兴趣的:(数据结构,C++,数据结构)