非递归方式!!利用栈实现,复杂度差不多,可以说基本一样,只是减少了递归方式的空间开销。
#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 阅读



