迷宮問題——最短程式碼,不到70行

geekchuang發表於2020-10-19

迷宮問題

1.題目描述

一組資料,輸入資料第1行為兩個正整數m和n,m表示迷宮高度,n表示迷宮寬度,m<100,n<100;第2行為兩個整數,分表表示起點的行列位置;第3為兩個整數,分別表示終點的行列位置;其後為m行資料,每行n個整數,表示迷宮對應位置的狀態,0表示通路,1表示障礙
2.程式碼例項
#include<cstdio> 
#include<iostream>
#include<algorithm>
#include<deque>
using namespace std;
struct base{
    int x,y,dir;
};

    int d[5][2]={{0,0},{0,1},{1,0},{0,-1},{-1,0}};    //依據題意先後搜尋的四個方向,右,下,左,上 
    deque<base> s;
    int a[102][102]={0};
    int m,n;  //在main函式外定義a[100][100]不然記憶體不夠 
    int startx,starty,endx,endy;
    base now;
    int flag=0; //flag=1表示已經找到終點,不需要在搜尋,剪枝想法 
    
void search(){
	if(now.x==endx&&now.y==endy){
		flag=1; return;
	}
	else{
		for(int i=1;i<=4;i++){
			if(a[now.x+d[i][0]][now.y+d[i][1]]==0){
				now.dir=i;
				s.push_back(now);					//儲存當前位置 
				a[now.x+d[i][0]][now.y+d[i][1]]=1;
				now.x+=d[i][0];
				now.y+=d[i][1];
				search();							//查詢下一個點 
				if(flag==1)return;
				else{								//遇到障礙,退一步
					 now=s.at(s.size()-1);
					 s.pop_back();					 
				}
			}
		}
	}
}

void print(base i){
	cout<<"("<<i.x<<","<<i.y<<","<<i.dir<<")"<<",";
}

int main(){
    cin>>m>>n;
    cin>>startx>>starty>>endx>>endy;
    for(int i=0;i<m+2;i++){					//給迷宮周圍圍上邊界 
        for(int j=0;j<n+2;j++){
            if(i==0||i==m+1||j==0||j==n+1)a[i][j]=1;
        }
    }
    for(int i=1;i<=m;i++){					//獲取迷宮元素 
        for(int j=1;j<=n;j++){
            cin>>a[i][j];
        }
    }
    now={startx,starty,1}; 					//初始位置 
    search();

    if(s.empty()){
        cout<<"no";   //沒有搜到到,輸出no 
    }else{
    	for_each(s.begin(),s.end(),print); 		//遍歷輸出 
    	cout<<"("<<endx<<","<<endy<<","<<1<<")";
	}

}

3.解釋說明

1.這個程式碼是採用的c++的stl模板,是我寫的,除錯過的,西電的同學想用的話直接複製貼上就行了,oj肯定能過(我也是西電的),所以基本上是csdn裡面最短的迷宮問題程式碼(至少我看到的還沒有比我短的程式碼,為啥要用stl吶,stl適合競賽,而且stl是別人除錯好的,程式碼簡短,不易出錯

2.這個程式碼的核心是dfs(深度優先搜尋演算法),也就是18-39行這21行程式碼,這個程式碼的備註我寫的很清晰,但估計還是會有很多人看不懂dfs是如何運作的,dfs主要是遞迴,所以需要很強的想象力,而且dfs的學習需要多除錯,我給大家貼上一張dfs的演算法框架圖以供參考

dfs模板
3.從這個問題延伸出來的一些問題,如全域性迷宮最短路徑,可以去掉剪枝演算法,程式碼中有註釋,還有列印路線圖等等都可以改改這個程式碼進行實現

4.stl模板類我使用的是deque,因為stack模板類被禁止遍歷,所以也就沒有迭代器,第一次我沒注意被坑慘了,雖然沒啥大問題,但要把stack例項重新放到陣列中,才能遍歷,要多寫20多行程式碼,大家注意,算是走過的坑吧,可以不用deque,也可以選用list模板

相關文章