問題描述
建築師邁克爾爲了救含冤入獄的哥哥,自己也想辦法進了監獄。現在他找到了哥哥,想帶着哥哥越獄。
可是監獄地形複雜,還有一道道的電網攔在面前。
電網非常危險,不到無路可走,邁克爾都不想嘗試鑽過電網。
請幫邁克爾兄弟設計一條穿過電網最少的路線。
(只能往相鄰的四個方向前進)
輸入
第一行:N,表示地圖的大小(10 <= N <= 1000)接下來N行N列,表示地圖,1表示有電網,0表示沒有,以空格隔開。
起點(1,1) 和終點(N, N) 一定沒有電網。
輸出
求到達終點最少穿過的電網數。需要注意的是,穿越緊挨在一起的兩個1,是穿過了兩道電網,而不是穿過了“1道厚度爲2的電網”。
樣例輸入
100 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;
}