7 条题解
-
0
非递归方式!!利用栈实现,复杂度差不多,可以说基本一样,只是减少了递归方式的空间开销。
#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; }
信息
- ID
- 84
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 776
- 已通过
- 118
- 上传者