1. 程式人生 > >bfs_迷宮問題 POJ - 3984

bfs_迷宮問題 POJ - 3984

題目:

定義一個二維陣列: 

int maze[5][5] = {

	0, 1, 0, 0, 0,

	0, 1, 0, 1, 0,

	0, 0, 0, 0, 0,

	0, 1, 1, 1, 0,

	0, 0, 0, 1, 0,

};


它表示一個迷宮,其中的1表示牆壁,0表示可以走的路,只能橫著走或豎著走,不能斜著走,要求程式設計序找出從左上角到右下角的最短路線。

Input

一個5 × 5的二維陣列,表示一個迷宮。資料保證有唯一解。

Output

左上角到右下角的最短路徑,格式如樣例所示。

Sample Input

0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

Sample Output

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

題目大意:

有一個迷宮,要求探索能否到達終點,如果可以的話輸出路徑

演算法:

bfs 佇列

程式碼:

#include<bits\stdc++.h>
#include<cstdio>
#include<iostream>
using namespace std;
struct node
{
	int x;
	int y;
	int f;
};
struct node que[2501]; //一共最多有2500個元素 
int a[51][51],b[51][51]; //a是儲存迷宮的陣列 b是標記陣列 

void print(int s)  //遞迴輸出
{
    if(que[s].f!=-1)
    {
        print(que[s].f);//根據查詢前一個的位置來遞迴
        cout<<"("<<que[s].x<<", "<<que[s].y<<")"<<endl;
    }
}

int main()
{
	int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; //方向陣列 用來遍歷四個方向 
	int head,tail; 
	int i,j,k,p,q,tx,ty,flag;
	for(i=0;i<5;i++)
		for(j=0;j<5;j++) 
			cin>>a[i][j]; //輸入迷宮資訊 
	head=tail=1;  
	que[tail].x=0;
	que[tail].y=0;  //迷宮起點入隊 
	que[tail].f=-1; //起點的father標記為-1 便於遞迴輸出路徑時使用 
	tail++;         
	b[0][0]=1;      //標記這個點已經走過 
	flag=0;         //flag在判斷終止時使用 
	while(head<tail)
	{
		for(k=0;k<4;k++)      
		{
			tx=que[head].x+next[k][0];
			ty=que[head].y+next[k][1];          //四個方向 
			if(tx<0||tx>4||ty<0||ty>4) continue; //越界 
			if(a[tx][ty]==0&&b[tx][ty]==0)  //這個點之前沒有走過 並且 是路 
			{
				b[tx][ty]=1;         //標記 
				que[tail].x=tx;    
				que[tail].y=ty;
				que[tail].f=head;    //入隊 
				tail++;
			}
			if(tx==4&&ty==4)
			{
				flag=1;
				break;       //到達終點 
			}
		}
		if(flag==1) break;
		head++;         //這個點已經探索完了 出隊 
	}
	cout<<"(0, 0)"<<endl;
	if(flag==1)
		 print(head);
	cout<<"(4, 4)";
	return 0;
}

解析:

這道題,要求輸出路徑,於是決定使用bfs演算法,採用佇列,可以儲存路徑。

que[].f 用來儲存這個元素的父節點,也就是說-儲存這個節點是從哪一個節點探索而來的。

 

當探索到終點後,使用自定義的遞迴print函式輸出路徑。

如果這個點的父親不是-1(也就是程式碼最開始,起點入隊時,標記的que[tail].f=-1)那麼就遞迴他的父親節點,知道這個元素的父親節點是起點,那麼就輸出他本身,這也就是為什麼要單獨輸出起點。 

至於為什麼單獨輸出終點座標是因為: 在判斷flag==1後就直接break了,沒有進行head++。

 

說完了路徑再來說 bfs 總的來說我對bfs的使用沒有dfs的順手

每探索完四個方向,這個時候就要出隊,這個地方的出隊並不是c++佇列的真正出隊,他還是儲存在了原本的陣列中,只是我們認為他已經出隊了。