NOIP -- 以往试题: 救援行动

上次有人问了一个题目,是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第一行二个整数nm。表示迷宫的大小为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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值