上次有人问了一个题目,是NOIP以前的一个试题, 是关于广度优先搜索的。题目如下:
救援行动
(rescue.c/cpp/pas)
Time Limit:1s Memory Limit:1000k
【问题描叙】
想必大家都认识传说中的AFY,现在AFY被传说中神秘的邪恶的Moligpy人抓住了!他急需你的救援。他被关在一个迷宫中。迷宫的长、宽不超过200。
迷宫中有不可以越过的墙以及监狱的看守。
AFY的朋友们组织了一些救援队来到了迷宫中。他们的任务是:接近AFY。我们假设接近AFY就是到达AFY所在的位置。
假设移动(只能向上、下、左、右4个方向移动)需要1单位时间,杀死一个看守也需要1单位时间。到达一个格子以后,如果该格子有看守,则一定要杀死(否则会死的很难看的……只见那个看守开了9倍狙镜……)。交给你的任务是,计算最少要多少单位时间,才能到达AFY所在的地方?
【输入格式】
输入文件rescue.in第一行二个整数n,m。表示迷宫的大小为n*m。
以后n行,每行m个时字符。其中“#”代表墙,“.”表示空地,“x”表示看守,“a”表示AFY,“r”表示救援队伍。
字母均为小写。
【输出格式】
输出文件rescue.out只有一行,代表救出AFY的最短时间。
如果救援小组永远不能达到AFY处,则输出“Poor AFY has to stay in the prison all his life.”
【输入样例】
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
【输出样例】
13
数据规模
对于30%的数据,n*m<=100;
对于全部的数据,n*m<=200*200。
看到题目的时候,大家都知道是关于广度优先搜索的,可是下手把它实现出来,还是有几个步骤的。
1、构建迷宫。
2、确定开始和结束位置。
3、执行搜索认为。
4、确定搜索的步骤,输出结果。
其中第一步,构建迷宫,有包括几个小的任务。
1、获取长宽。
2、设定边界。
3、读取一行输入,解析字符,设置是否可以通过标志。(顺便也确定了搜索的开始和结束位置)
发现网上很难找到完整的代码,或者注释不够,或者同类但不是对应这道题,或者比较粗燥(比如在出队的时候,没有判断这个节点是否已经处理过,造成循环,溢出),就把自己的测试代码列了一下。中间多加了一些输出信息。
(*
此处的常量定义,容易让人迷惑。
仅仅是为了在后来的遍历过程中,是代码看上去好看一些。避免使用4次同样的if语句来变量一个节点的四个相邻节点。
*)
const
offset_x : array[1..4] of integer = (1,0,-1,0);
offset_y : array[1..4] of integer = (0,1,0,-1);
type
track_type = record
x, y, last : longint; // the level of its parent node.
end;
var
str : string; // read the lines in the input file and checkout the char to setup the map.
map_cols, map_lines, start_x, start_y, end_x, end_y : longint;
map : array[0..201, 0..201] of boolean; // the max size is 200, so we add 2 pointes for the border.
visited : array[0..200, 0..200] of boolean; // record whether the node has been processed.
link_queue : array[1..10000] of track_type;
travel_list : array[1..10000] of track_type;
end_node_in_queue : longint; // store the position of the end point in the queue.
i, j, step_number : longint;
procedure BFS(sx, sy, ex, ey : longint);
var
head, tail : longint;
x, y, i : longint;
nx, ny : longint; // node arround with current point.
begin
// init.
head := 1;
tail := 1;
link_queue[1].x := sx;
link_queue[1].y := sy;
//
while head <= tail do
begin
x := link_queue[head].x;
y := link_queue[head].y;
if (x = ex) and (y = ey) then
begin
writeln('=============== End point.');
end_node_in_queue := head;
exit;
end; // end of meet the end point.
writeln('x=', x, ' y=', y, ' head=', head, ' tail=', tail);
// mark this node has been checked.
visited[x, y] := true;
// This loop is just to save the 4 times same statement to checking the neighbor node.
for i := 1 to 4 do
begin
nx := x + offset_x[i];
ny := y + offset_y[i];
if (not map[nx, ny]) and (not visited[nx, ny]) then
begin
inc(tail);
link_queue[tail].x := nx;
link_queue[tail].y := ny;
link_queue[tail].last := head;
end;
end; // end loop of the 4 direction.
inc(head);
// writeln('=== in loop. x :', x, ' y :', y, ' tail is: ', tail, ' head is: ', head);
end; // end while loop.
end; // end of the procedure.
begin
// 1. read the maze size.
assign(input,'E:/NOIP/test/rescue.in');
reset(input);
readln(map_lines, map_cols);
// 2. Setup the maze.
for i := 1 to map_lines do
begin
readln(str);
for j := 1 to map_cols do
begin
case str[j] of
'#' : map[i, j] := true; // wall.
'x' : map[i, j] := true; // guarder.
'.' : map[i, j] := false; // space.
'a' : // the end point.
begin
end_x := i;
end_y := j;
end;
'r' : // the start point.
begin
start_x := i;
start_y := j;
end
end; // end case.
end;
end; // end loop.
// 3. Setup the maze border.
for i := 1 to map_lines do
begin
map[i, 0] := true;
map[i, map_cols + 1] := true;
end;
for i := 1 to map_cols do
begin
map[0, i] := true;
map[map_lines + 1, i] := true;
end;
writeln('== start point (', start_x, ',', start_y, '). end point (', end_x, ',', end_y, ').');
// print the maze, test using.
writeln('====== The maze map: ');
for i := 1 to map_lines do
begin
for j := 1 to map_cols do
begin
if map[i,j] then
write('#')
else
write('0');
end;
writeln();
end;
writeln('======');
// 4. Call the BFS.
BFS(start_x, start_y, end_x, end_y);
// 5. Checkout the shortest path.
if (end_node_in_queue<= 0) then
begin
writeln('Poor AFY has to stay in the prison all his life.');
exit;
end;
writeln('the end node level is: ', end_node_in_queue);
i := end_node_in_queue;
step_number := 1;
while i <> 0 do
begin
travel_list[step_number] := link_queue[i];
inc(step_number);
i := link_queue[i].last;
end;
writeln('-- total steps: ', step_number - 1);
for i := step_number-1 downto 1 do
writeln(travel_list[i].x, ' ', travel_list[i].y);
close(input);
end.
测试的输出结果如下:
== start point (2,7). end point (2,3).
====== The maze map:
#0#####0
#00#0000
#00##000
00#00#0#
#000##00
0#000000
00000000
======
x=2 y=7 head=1 tail=1
x=3 y=7 head=2 tail=4
x=2 y=8 head=3 tail=7
x=2 y=6 head=4 tail=9
x=4 y=7 head=5 tail=11
x=3 y=8 head=6 tail=12
x=3 y=6 head=7 tail=12
x=3 y=8 head=8 tail=12
x=1 y=8 head=9 tail=12
x=3 y=6 head=10 tail=12
x=2 y=5 head=11 tail=12
x=5 y=7 head=12 tail=12
x=6 y=7 head=13 tail=14
x=5 y=8 head=14 tail=17
x=7 y=7 head=15 tail=18
x=6 y=8 head=16 tail=20
x=6 y=6 head=17 tail=21
x=6 y=8 head=18 tail=23
x=7 y=8 head=19 tail=24
x=7 y=6 head=20 tail=24
x=7 y=8 head=21 tail=25
x=7 y=6 head=22 tail=25
x=6 y=5 head=23 tail=26
x=7 y=8 head=24 tail=28
x=7 y=5 head=25 tail=28
x=7 y=5 head=26 tail=29
x=7 y=5 head=27 tail=30
x=6 y=4 head=28 tail=31
x=7 y=4 head=29 tail=34
x=7 y=4 head=30 tail=35
x=7 y=4 head=31 tail=36
x=7 y=4 head=32 tail=37
x=5 y=4 head=33 tail=38
x=6 y=3 head=34 tail=40
x=7 y=3 head=35 tail=42
x=7 y=3 head=36 tail=43
x=7 y=3 head=37 tail=44
x=7 y=3 head=38 tail=45
x=4 y=4 head=39 tail=46
x=5 y=3 head=40 tail=47
x=7 y=3 head=41 tail=48
x=5 y=3 head=42 tail=49
x=7 y=2 head=43 tail=50
x=7 y=2 head=44 tail=51
x=7 y=2 head=45 tail=52
x=7 y=2 head=46 tail=53
x=4 y=5 head=47 tail=54
x=5 y=2 head=48 tail=54
x=7 y=2 head=49 tail=55
x=5 y=2 head=50 tail=56
x=7 y=1 head=51 tail=57
x=7 y=1 head=52 tail=58
x=7 y=1 head=53 tail=59
x=7 y=1 head=54 tail=60
x=4 y=2 head=55 tail=61
x=7 y=1 head=56 tail=63
x=4 y=2 head=57 tail=64
x=6 y=1 head=58 tail=66
x=6 y=1 head=59 tail=66
x=6 y=1 head=60 tail=66
x=6 y=1 head=61 tail=66
x=3 y=2 head=62 tail=66
x=4 y=1 head=63 tail=68
x=6 y=1 head=64 tail=68
x=3 y=2 head=65 tail=68
x=4 y=1 head=66 tail=70
x=3 y=3 head=67 tail=70
x=2 y=2 head=68 tail=71
x=3 y=3 head=69 tail=73
x=2 y=2 head=70 tail=74
=============== End point.
the end node level is: 71
-- total steps: 15
2 7
3 7
4 7
5 7
6 7
6 6
6 5
6 4
5 4
5 3
5 2
4 2
3 2
3 3
2 3