问题描述
建筑师迈克尔为了救含冤入狱的哥哥,自己也想办法进了监狱。现在他找到了哥哥,想带着哥哥越狱。
可是监狱地形复杂,还有一道道的电网拦在面前。
电网非常危险,不到无路可走,迈克尔都不想尝试钻过电网。
请帮迈克尔兄弟设计一条穿过电网最少的路线。
(只能往相邻的四个方向前进)
输入
第一行: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;
}