廣度優先算法 越獄

問題描述

建築師邁克爾爲了救含冤入獄的哥哥,自己也想辦法進了監獄。現在他找到了哥哥,想帶着哥哥越獄。


可是監獄地形複雜,還有一道道的電網攔在面前。

電網非常危險,不到無路可走,邁克爾都不想嘗試鑽過電網。

請幫邁克爾兄弟設計一條穿過電網最少的路線。

(只能往相鄰的四個方向前進)

輸入

第一行:N,表示地圖的大小(10 <= N <= 1000)

接下來N行N列,表示地圖,1表示有電網,0表示沒有,以空格隔開。

起點(1,1) 和終點(N, N) 一定沒有電網。

輸出

求到達終點最少穿過的電網數。

需要注意的是,穿越緊挨在一起的兩個1,是穿過了兩道電網,而不是穿過了“1道厚度爲2的電網”。

樣例輸入

10
0  0  0  0  1  1  0  1  1  1
1  0  1  0  1  0  1  1  0  1
0  0  0  0  1  0  1  0  1  1
1  1  1  1  1  1  0  1  1  0
1  0  0  0  0  0  0  1  1  0
0  0  1  1  1  1  1  1  0  0
0  0  1  0  0  0  0  1  1  1
0  0  0  0  1  0  0  0  0  0
1  0  0  1  1  1  0  1  1  1
0  1  0  0  0  0  1  0  1  0

樣例輸出

2


分析

這題的數據量比較大,達到1000,假如使用DFS,光沿着邊走,就已經到達2000,遞歸達到2000層,棧是絕對會爆的。

所以這題考慮使用BFS進行遍歷。而思路則是,一開始找出被1包圍的區域,走到無路可走時,進行突破,result+1;

突破之後繼續尋找下一個被1包圍的區域,直到到達終點。

具體做法則是,使用雙隊列,一個存放0,一個存放1。在BFS的時候,把需要訪問的0放入0隊列,1放入1隊列。

當0隊列爲空時,表示無路可走。這時清空0隊列,把1隊列數據轉移到0隊列作爲下一次BFS的數據。如此循環直到訪問到右下角的終點


代碼

#include <stdio.h>

using namespace std;

#define MAX 1002
#define DEBUG 0

typedef struct _NODE_ {
	unsigned int x;
	unsigned int y;
}st_node;

int N;
char map[MAX][MAX];
int result = 0;
st_node list0[MAX*MAX];  //數組太小會導致越界
st_node list1[MAX*MAX];

void BFS (st_node node) {
	st_node tmp;
	int head0 = 0, tail0 = 0;
	int head1 = 0;
	
	list0[head0++] = node;	   //in_queue

	while(tail0 <= head0) {
		node = list0[tail0++]; //out_queue

		for (int i = 0; i < 4; i++) {
			tmp = node;

			if (i == 0) {         //向下
				tmp.x++;
			} else if (i == 1) {  //向上
				tmp.x--;
			} else if (i == 2) {  //向右
				tmp.y++;
			} else if (i == 3) {  //向左
				tmp.y--;
			}

			if ( map[ tmp.x ][ tmp.y ] == 2 ) {       // 已訪問
				continue;
			} else if ( map[ tmp.x ][ tmp.y ] == 0 ) { // 進入0隊列
				list0[ head0++ ] = tmp;
				map[ tmp.x ][ tmp.y ] = 2;

			} else if ( map[ tmp.x ][ tmp.y ] == 1 ) { // 進入1隊列
				list1[ head1++ ] = tmp;
				map[ tmp.x ][ tmp.y ] = 2;
			}
		}

		if ( tail0 == head0 ) {	//找到被1包圍的區域,必須突破區域

			result++;    //增加需要突破的電網數目
#if DEBUG 
			for (int x = 0; x <= N+1; x++) {
				for (int y = 0; y <= N+1; y++) {
					printf("%d ", map[x][y]);
				}
				printf("\n");
			}
#endif
			//將1隊列的數據複製到0隊列,作爲下一次BFS的數據
			for (int i = 0; i < head1; i++) {
				list0[i] = list1[i];
			}

			head0 = head1;
			tail0 = head1 = 0;
		}

		if (map[N][N] == 2)
			break;
	}
}

int main(int argc, char *argv[])
{

#if DEBUG 
	freopen("input.txt","r", stdin);
#endif

	scanf("%d", &N);

	int edge = N + 1;
	for ( int i = 0; i <= edge; i++ ) {
		map[0][i] = 2;
		map[i][0] = 2;
		map[edge][i] = 2;
		map[i][edge] = 2;
	}
	
	int tmp = 0;
	for ( int i = 1; i <= N; i++ ) {
		for ( int j = 1; j <= N; j++ ) {
			scanf("%d", &tmp);
			map[i][j] = tmp;
		}
	}	


	st_node node;
	node.x = 1;
	node.y = 1;

	BFS(node);

	printf("%d", result);

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章