用递归实现求一个迷宫是否有通路

今天终于把昨天下午没写出来的迷宫求是否有通路的cpp写出来了

使用递归实现的,不过算法的质量不怎么样,使用穷举法实现的。

在网上搜了一下,发现还有很多的更优的算法,哈哈,不过怎么说都是自己一个个地代码敲出来的。

特点是发现在linux下面调试真的有时候自己会崩溃,还好最终还是搞出来了。

哈哈,发上来给类似我这种的算法新手来一起分享一下;

路径就记录在栈里面,需要得出具体路径的可以小改一下就行了。

findRoad.cpp

//迷宫求解问题思路
//1.用一个矩阵来表示迷宫,即n*m数组
//用穷举法实现;即从入口出发,顺着某一个方向向前探索,若能走通,则继续往前走;
//若到了某一点走不通,则标记该点为不可达
//否则原路返回,换一个方向再继续探索
//具体的请看算法解释
#include <iostream>
using namespace std;
#include "stack.cpp"
struct box{
	bool status;//用于判断该处是否可通
	int direct;//用于标记在这里向哪个方向探索过了,
	//1234分别代表向左上右下的顺序探索,即顺时针方向
};
struct posType//用于记录某一点的坐标值
{
	int x;
	int y;
};
bool isEqueal(posType a,posType b)//跟arriived一样,不过名字变了而已
{
	if(a.x==b.x&&a.y==b.y)
		return true;
	return false;

}
bool arrived(posType start,posType end)//判断是否已经到达出口
{
	if(start.x==end.x&&start.y==end.y)
		return true;
	return false;

};
static mStack<posType> ms;//用于存放经过的路径
const int MAXLINE=5;//需要的时候再改
const int MAXROW=5;
bool findRoad(box (*arr)[MAXROW],posType start,posType end)//注意二维数组的指针表示
{
	int x=start.x;
	int y=start.y;
	if(arrived(start,end))//如果到达
		return true;
	//还会有下面这种情况
	//应该这样表达才对arr+start.x*MAXROW+start.y)->status
	//而不是(*arr+i)+j
	if((*arr+x*MAXROW+y)->status==false)//假设仅剩该点且该点四周都不可达,则路到了尽头!!
		return false;
	posType temp;
	if(ms.isEmpty())	//如果栈空
		ms.Push(start);		//将当前位置入栈
	else 	//判断是否是上一个点,避免重复入栈
	{
		ms.GetTop(temp);
		if(!isEqueal(temp,start))
			ms.Push(start);
	}

	switch((*arr+x*MAXROW+y)->direct)//检测往哪个方向走过了
	{
		//derect=0代表未向任何方向探索过,应向左探索
		//=1代表要向上探索
		case 0:if(y-1>-1&&(*arr+x*MAXROW+y-1)->status)//向左方探索,如果没有越界并且左方是可达的
			{
					//posType newStart(x-1,y);//以左方作为新起点
					posType newStart;
					newStart.x=x;
					newStart.y=y-1;
					(*arr+x*MAXROW+y)->direct=1;//应该是该点=1;该点探索过了而不是下一点
					//arr[newStart.x][newStart.y].direct=1;//探索的方向+1
					findRoad(arr,newStart,end);//以新起点开始探索
			}
			else//倘若数组越界了,或者左方不可达,则向上探索
			{
				(*arr+x*MAXROW+y)->direct=1;//令其=1,再递归调用
				findRoad(arr,start,end);//起点不变
			};break;
		case 1:if(x-1>-1&&(*arr+(x-1)*MAXROW+y)->status)//向上方探索,如果没有越界并且上方是可达的
				{
//					posType newStart(x,y-1);//以该起点作为新点
					posType newStart;
					newStart.x=x-1;
					newStart.y=y;
					(*arr+x*MAXROW+y)->direct=2;//应该是该点=1;该点探索过了而不是下一点
					//arr[newStart.x][newStart.y].direct=2;//探索的方向=2
					findRoad(arr,newStart,end);//以新起点开始探索
				}
				else//倘若数组越界了,则向上探索
				{
					(*arr+x*MAXROW+y)->direct=2;//令其=2,再递归调用,即指示其向下一个方向探索
					findRoad(arr,start,end);//起点不变
				};break;
		case 2:	if(y+1<MAXROW&&(*arr+x*MAXROW+y+1)->status)//向右方探索,如果没有越界并且右方是可达的
				{
					//posType newStart(x+1,y);//以该起点作为新点
					posType newStart;
//					newStart.x=x+1;
					newStart.x=x;//向右应该是y+1
					newStart.y=y+1;
					(*arr+x*MAXROW+y)->direct=3;
					//arr[newStart.x][newStart.y].direct=3;//探索的方向=3
					findRoad(arr,newStart,end);//以新起点开始探索
				}
				else//倘若数组越界了或者不可达,则向下探索
				{
					(*arr+x*MAXROW+y)->direct=3;//令其=3,再递归调用,即指示其向下一个方向探索
					findRoad(arr,start,end);//起点不变
				};break;
		case 3:	if(x+1<MAXLINE&&(*arr+(x+1)*MAXROW+y)->status)//向下方探索,如果没有越界并且下方是可达的
				{
					//posType newStart(x,y+1);//以该起点作为新点
					posType newStart;
					newStart.x=x+1;
					newStart.y=y;
					(*arr+x*MAXROW+y)->direct=4;
					//arr[newStart.x][newStart.y].direct=4;//探索的方向=3
					findRoad(arr,newStart,end);//以新起点开始探索
				}
				else//倘若数组越界了或者不可达,更改此点为不可达
				{
					(*arr+x*MAXROW+y)->direct=4;//令其=3,再递归调用,即指示其向下一个方向探索
					findRoad(arr,start,end);//起点不变
				};break;
		case 4:	(*arr+x*MAXROW+y)->status=false;//当四个方向都探索完了之后,均没有通路时,标记该点为不可达状态

				posType t;//将当前点出栈
				ms.Pop(t);//
				if(ms.isEmpty())//如果此时栈已经空了,说明没有路可以回头了,路不通
					return false;
				ms.Pop(start);//令上一路径为起点,递归找路
				findRoad(arr,start,end);
				break;
	};
};

stack.cpp

//用于实现栈的操作
#include <iostream>
using namespace std;
//const int MAX=100;//栈最大长度值为100,用数组实现栈
//写成模板类是为了方便我以后使用
template <class T>
class mStack{
	private:
		enum {MAX=1000};
		T arr[MAX];
		int Size;
		int top;//用于指示栈顶位置
	public:
		mStack(	)//构建空栈
		{
		  top=-1;//下标为-1则为空栈
		  Size=0;
		}
		bool isEmpty()
		{
			return top==-1;
		}
		bool isFull()
		{
			return top==MAX-1;
		}
		bool Push(T &item)
		{
			if(isFull())
			{
				cout<<"stack is full!"<<endl;
				return false;
			}
			//++top;
			//arr[++top]=item;
			arr[++top]=item;//因为下标从-1开始,使用前+1
			//cout<<"this "<<top<<" item push values is :"<<arr[top]<<endl;
			Size++;
			return true;
		}
		bool Pop(T &item)
		{
			if(isEmpty())
			{
				cout<<"stack is empty!"<<endl;
				return false;
			}
			item=arr[top--];//因为下标从-1开始,top指向当前最后一个元素,使用后-1
			//cout<<"this "<<top<<" item pop values is :"<<arr[top]<<endl;
			Size--;
			return true;
		}
		bool GetTop(T &item)
		{
			if(!isEmpty())
			{
				item=arr[top];
				return true;
			}
			return false;
		}
		int size()
		{
			return Size;
		}

};

test.cpp

#include <fstream>
#include <cstdlib>
#include <ctime>
#include "all.cpp"
const int MAXL=5;
const int MAXR=5;

int main()
{
	ofstream fout;//("test1.txt");//,ios_base::app);//,ios_base::app);
	fout.open("test1.txt",ios_base::app);

	if(!fout.is_open())
		cerr<<"open failer!"<<endl;

	//box (*b)[MAXR];
	box (*b)[MAXR]=new box[MAXL][MAXR];
	ifstream fin("tx.txt");//从文件中读取迷宫
	if(!fin.is_open())
		cerr<<"fin open failure!"<<endl;

	for(int i=0;i<MAXLINE;i++)
		{
		for(int j=0;j<MAXROW;j++)
			{
				int num;
				fin>>num;
				//*(*(b+i)+j)=new box;
				if(num==1)
					(*(b+i)+j)->status=false;//给迷宫里的box赋值
					//(*(ar+i)+j)->status=false;
				else
					(*(b+i)+j)->status=true;

					(*(b+i)+j)->direct=0;
			}
		}

	fin.close();
	posType start;
	start.x=0;
	start.y=1;

	posType end;
	end.x=0;
	end.y=3;

	(*(b+start.x)+(start.y))->status=true;
	(*(b+end.x)+end.y)->status=true;

	for(int i=0;i<MAXLINE;i++)
	{

		for(int j=0;j<MAXROW;j++)
		{
			if((*(b+i)+j)->status)
				fout<<"0 ";
			else
				fout<<"1 ";
		}
		fout<<endl;
	}
	fout<<endl<<endl;
	fout.close();	

	if(findRoad(b,start,end))
		cout<<"has load!"<<endl;
	else
		cout<<"no load "<<endl;	

}

tx.txt

//可以自己设置迷宫路径和出发点以及出口

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

用递归实现求一个迷宫是否有通路

时间: 2024-10-05 12:03:19

用递归实现求一个迷宫是否有通路的相关文章

求一个数组的子数组的最大和

如题:求一个数组的子数组的最大和,要求O(n)时间复杂度. 由于有了O(n)时间复杂度的限制,所以暴力求解的O(n^2)方法肯定不行.再考虑递归求一个数组a[n]的子数组的最大和,可以分解为a[i]子数组的最大和以及a[n-i-1]之间的某种情况 a[n]的子数组最大和等于a[i]子数组的最大和: a[n]的子数组最大和等于a[n-i-1]: a[n]的子数组最大和跨a[i]和a[n-i-1]: 递归实现的时间复杂度为O(nlg(n)).最后考虑时间复杂度为O(n)的动态规划实现. /** *

算法题:求一个序列S中所有包含T的子序列(distinct sub sequence)

题: 给定一个序列S以及它的一个子序列T,求S的所有包含T的子序列.例: S = [1, 2, 3, 2, 4] T = [1, 2, 4] 则S的所有包含T的子序列为: [1, 2, 3, 2, 4] [1, 2, 3, 4] [1, 2, 2, 4] [1, 2, 4] 解: 首先可以拆解为两个问题: 1. 求S的所有子序列:其中又涉及到去重的问题. 2. 求S的所有子序列中包含T的子序列. 暂时先不考虑去重,看看问题1怎么解: 一.求S的子序列 单纯求一个序列的所有子序列的话,就是求序列的

求一个集合的所有子集问题

转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/31042651 作者:小马 一个包含n个元素的集合,求它的所有子集.比如集合A= {1,2,3}, 它的所有子集是: { {1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}, @}(@表示空集). 这种问题一般有两种思路,先说说第一种,递归.递归肯定要基于一个归纳法的思想,这个思想用到了二叉树的遍历,如下图所示: 可以这样理解这张图,从集合A的每

求一个数组的最大k个数(java)

问题描述:求一个数组的最大k个数,如,{1,5,8,9,11,2,3}的最大三个数应该是,8,9,11 问题分析: 1.解法一:最直观的做法是将数组从大到小排序,然后选出其中最大的K个数,但是这样的解法,复杂度是O(logn*n),但是有时候并不需要排序,用简单的选择排序,或者是冒泡排序,那么就K轮的交换或者是选择,就可以得出结论,复杂度是O(n*k),当K很大的时候排序可能是更好的解法,当K小的时候用选择或者是冒泡效率会更加的高.但是这都是会对前K个数进行排序,所以效率不高,当K很大的时候,以

求一个包加减乘除和小括号的字符串的结果

解题思路和代码原型来源于牛课网, 我自己实现了一遍,添加了部分注释 1 package problems_2016_08_10; 2 3 import java.util.LinkedList; 4 /* 5 总述: 6 一共有五个函数分别是: 7 8 getvalue(): 9 参数:待求的字符串. 10 作用:一个启动函数,调用value函数 11 返回值:返回value函数返回值的第一个参数,就是求出的值 12 13 value(): 14 参数:总的待求的字符串,从哪一个位置开始求 15

分治策略结合递归思想求最大子序列和

我的主力博客:半亩方塘 对于 <数据结构与算法分析--C语言描述> 一书第 20 页所描述的算法 3,相信会有很多人表示不怎么理解,下面我由具体问题的求解过程出发,谈谈我自己的理解: 首先,什么是分治法呢?所谓 分治法,就是 将一个问题的求解过程分解为两个大小相等的子问题进行求解,如果分解后的子问题本身也可以分解的话,则将这个分解的过程进行下去,直至最后得到的子问题不能再分解为止,最后将子问题的解逐步合并并可能做一些少量的附加工作,得到最后整个问题的解.在求解原来整个问题的算法思想,与求解每一

(转)递归树求递归算法的时间复杂度

本文转载:http://www.cnblogs.com/wu8685/archive/2010/12/21/1912347.html 递归算法时间复杂度的计算方程式一个递归方程: 在引入递归树之前可以考虑一个例子: T(n) = 2T(n/2) + n2 迭代2次可以得: T(n) = n2 + 2(2T(n/4) + (n/2) 2) 还可以继续迭代,将其完全展开可得: T(n) = n2 + 2((n/2) 2 + 2((n/22)2 + 2((n/23) 2 + 2((n/24) 2 +-

java实现求一个数组里最大值和最小值之前缺省的数的算法

问题描述: 求一个数组里最大值和最小值之间缺省的数,例如 int arrDemo = {1, 3, 7};  那么就要输出最小值1和最大值7之间缺少的数字2,4,5,6 代码如下,有更好的思路欢迎大家在评论区留言讨论 1 package test; 2 3 public class Test { 4 5 static int[] array = { 6 -10,0,3,3,9 7 }; 8 9 private static void printEmptyItems(int[] array) {

求一个n阶方阵对角线元素之和

求一个n阶方阵对角线元素之和? public class shuixian { public static void main(String[] args) {  // TODO 自动生成的方法存根  int sum=0;  Scanner reader=new Scanner(System.in);  System.out.println("请输入方阵的阶数");  int n=reader.nextInt();  int[][] a=new int[n][n];  for(int