返回题解分享
讨论 / 题解分享/ 帖子详情

走迷宫输出路径 - 题解

非递归方式!!利用栈实现,复杂度差不多,可以说基本一样,只是减少了递归方式的空间开销。

#include<cstdio>
#include<iostream>
using namespace std;

int posit[16][16];   //记录位置; 
int flag[16][16];	//记录是否走过 
int end1,end2;		//结束点 
int dy[4]={0,-1,0,1};    //方向 
int dx[4]={-1,0,1,0};
int n,m; 
int count=0; 
int mstate[300][2];    //数组模拟的栈     mstate[][0]存放y坐标,mstate[][1]存放x 
int top=1;				//栈顶指针,指向栈顶元素的下一个位置 

int whatp(int y,int x){        //当元素出站时会执行该函数,该函数为了计算回溯的方向,得出我下一次要从哪个方向开始 
	for(int i=0;i<4;++i){		//因为前面定义了dy,dx,顺序是左上右下,即为i=0,1,2,3
		if(y==dy[i]&&x==dx[i]) return i+1; 	//比如我是从上面回溯过来的,那么i就是1,于是我return i+1 也就是2,告知下一次要从(i=2)右开始找 
	}
	return 4;     //实际上不可能会有for循环外的情况,这里只是加上reutrn防止报错 
}
int main(){
	cin>>n>>m;
	int be1,be2;
	for(int i=1;i<=n;++i)						
	for(int j=1;j<=m;++j) cin>>posit[i][j];	
	char tmp[20];
	cin>>be1>>be2>>end1>>end2;
	mstate[0][0]=be1;       //栈底先加入第一个元素,也就是起始点 
	mstate[0][1]=be2;
	int nowx=be2,nowy=be1;    //表示当前走到了哪 
	int newx=be2,newy=be1;   	//前进的坐标 
	int oribx=0,oriby=0;    //从哪里回溯过来的坐标 
	int ifnext=0;         //是否有坐标可以让我前进 
	int p=0;			//从哪个方向开始 
	while(top>0){  
						//建议先从51行开始看 
		if(nowy==end1&&nowx==end2){
			for(int k=0;k<top-1;k++){           //这里就是走到终点时要打印路径了 
				sprintf(tmp,"(%d,%d)->",mstate[k][0],mstate[k][1]);
				cout<<tmp;
			}
			count++;     //找到一条路径就加一次 
			sprintf(tmp,"(%d,%d)",end1,end2);       
			cout<<tmp<<endl;
			top--;                              //我还要接着寻找有没有其他路径   所以回溯 
			nowy=mstate[top-1][0];nowx=mstate[top-1][1];     //这里的原理和69行一样 
			oriby=mstate[top][0];oribx=mstate[top][1];
			flag[oriby][oribx]=0;
			p=whatp(oriby-nowy,oribx-nowx);
		}
		else {
			ifnext=0;   
			for(int i=p;i<4;++i){    //比如我p=0,那么我就从左开始 左-》上-》右-》下  如果p=2,那么我就是从右开始 右-》下  
			newy=nowy+dy[i];newx=nowx+dx[i];     //计算出下一个想要走的坐标 
			if(newy<=n&&newy>0&&newx<=m&&newx>0&&flag[newy][newx]!=1&&posit[newy][newx]!=0){//判断下一个坐标能不能走 
				p=0;            //因为下个坐标是新的,那它一定是从 左上右下 开始走 
				nowy=newy;nowx=newx;     //更新位置 
				mstate[top][0]=newy;mstate[top][1]=newx;   //入栈 
				flag[newy][newx]=1;     //标记走过 
				top++;
				ifnext=1;            //这一次存在可以往下走的坐标 
				break;
			}
		}
		}			

		if(ifnext) continue;      //既然存在 可以往下走的坐标 那就不需要回溯了,跳过下面代码从头开始 
		
		top--;     	// 不存在可以往下走的坐标   那就要回溯了   栈顶指针向回走 
		nowy=mstate[top-1][0];nowx=mstate[top-1][1];         //回到上一个坐标,前面提到栈顶指针,指向栈顶元素的下一个位置  所以当前栈顶元素就top-1 
		oriby=mstate[top][0];oribx=mstate[top][1];     //top-1指向当前的栈顶元素,那么top指向的就是刚刚的栈顶元素 
		flag[oriby][oribx]=0;             //把刚才回溯过来的点标记为没走过 
		p=whatp(oriby-nowy,oribx-nowx);     //这里相当于计算出dy,dx,可以重写到函数定义处看看解释 
											//计算p值就是为了防止我下一次又走向刚刚回溯过来的点,陷入死循环 
	}
	if(count==0) cout<<-1;   //没有路径输出-1 
		
	return 0;
	
}
0 回复 0 转发 0 喜欢 5 阅读
回复 (0)
默认 最新
暂无回复,快来抢沙发!