7 条题解

  • 0
    @ 2024-4-19 14:36:59

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

    #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
    上传者