[数据结构]求解迷宫最短路径问题

一、问题概述

       之前,我们了解了如何实现迷宫问题(对于迷宫只有一个出口可以通的情况),事实上我们的迷宫有多个出口,对于每条路径来说,有长有短,所以在这里,我们讨论一下迷宫的最短路径,即迷宫路径的最优解问题。


二、解决方案


       对于这样一个迷宫:

    《[数据结构]求解迷宫最短路径问题》


   注:数字为0的表示可以通过,数字为1的表示不可以通过。

   从入口坐标:(2,0)开始,可以到达出口位置的通路总共有三条。可想而知,肯定得把每一条路径都得遍历一遍,记录每条路径的长度。我们这里采用了递归的思想。

求解最短路径的办法:


(1)将入口点标记起来,给其赋值;


(2)每次访问的下一个位置就是前一个位置的值+1,直至一条路径成功通往出口;


(3)如果访问下一条路径的时候,递归会回退,在这里回退时它还会检测是否有通路,(上上节讲迷宫问题时有具体实现,可以去参照),这时由于我们赋的值已经改变了,所以此时判断的条件为如果它的下一个位置的值+1>当前的位置的值,它就可以通过。


(4)当每条路径走完后,会显示最后出口的值,这样就知道哪条路径最短啦。


图示如下:

                                               《[数据结构]求解迷宫最短路径问题》


三、实现代码


//Maze1.h

#include<iostream>
using namespace std;
#include<assert.h>
#include<stack>

struct Pos
{
	int _row;
	int _col;
};

void GetMaze(int *Maze,size_t N)
{
	FILE* fout = fopen("Maze1.txt","r");
	assert(fout);
	for(size_t i = 0; i < N; ++i)
	{
		for(size_t j = 0; j < N; )
		{
			int value = fgetc(fout);
			if(value == '1' || value == '0')
			{
				Maze[i*N+j] = value - '0';
				++j;
			}
			else if(value == EOF)
			{
				cout<<"Maze error!"<<endl;
				return;
			}
		}
	}
}

bool IsCheckPath(int *maze,size_t n,Pos cur,Pos next)
{
	if((next._row < 0 || next._row >= 10) 
		|| (next._col < 0 || next._col >= 10)
		||(maze[next._row*n+next._col] == 1))
	{
		return false;
	}
	
	if(maze[next._row*n+next._col] == 0)
	{
		return true;
	}

	return maze[next._row*n+next._col]+1 > maze[cur._row*n+cur._col];
}


//递归
void GetMazePath(int *maze,size_t n,Pos entry,stack<Pos>& s,stack<Pos>& ss)
{
		Pos cur;
		Pos next;
		s.push(entry);
		next = entry;
		if(entry._row == n-1)
		{
			if(ss.empty() || s.size() < ss.size())
			{
				ss = s;
			}
			s.pop();
			return;
		}
		

		//探测上下左右
		//上
		next = entry;
		cur = next;
		next._row-=1;
		if(IsCheckPath(maze,n,cur,next))
		{
			maze[next._row*n+next._col] = maze[cur._row*n+cur._col]+1;
			GetMazePath(maze,n,next,s,ss);
		}
		//右
		next = entry;
		cur = next;
		next._col+=1;
		if(IsCheckPath(maze,n,cur,next))
		{
			maze[next._row*n+next._col] = maze[cur._row*n+cur._col]+1;
			GetMazePath(maze,n,next,s,ss);
			
		}

		//下
		next = entry;
		cur = next;
		next._row+=1;
		if(IsCheckPath(maze,n,cur,next))
		{
			maze[next._row*n+next._col] = maze[cur._row*n+cur._col]+1;
			GetMazePath(maze,n,next,s,ss);
			
		}

		//左
		next = entry;
		cur = next;
		next._col-=1;
		if(IsCheckPath(maze,n,cur,next))
		{
			maze[next._row*n+next._col] = maze[cur._row*n+cur._col]+1;
			GetMazePath(maze,n,next,s,ss);
		}

		//四方都不通

		s.pop();
}

void PrintMaze(int *maze,size_t n)
{
	cout<<"迷宫显示:>"<<endl;
	for(size_t i = 0; i < n; ++i)
	{
		for(size_t j = 0; j < n; ++j)
		{
			cout<<maze[i*n+j]<<" ";
		}
		cout<<endl;
	}
}

//Maze1.cpp

#include"Maze1.h"

//用栈和递归实现迷宫问题
const size_t N = 10;

void FunTest()
{
	int Maze[N][N];
	Pos entry = {2,0};
	stack<Pos> ss;
	stack<Pos> ss1;
	GetMaze((int*)Maze,N);
	Maze[entry._row][entry._col] = 2;
	GetMazePath((int*)Maze,N,entry,ss,ss1);
	cout<<"迷宫是否有出口?"<<!ss.empty()<<endl;
	PrintMaze((int*)Maze,N);
}

int main()
{
	FunTest();
	return 0;
}

四、运行结果


《[数据结构]求解迷宫最短路径问题》


    原文作者:蚁群算法
    原文地址: https://blog.csdn.net/xxpresent/article/details/53519362
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞