【Nov 11 P4,分层BFS】潜入辛迪加

 

  
    
【题目描述】(来源:BYVoid的WOW模拟赛Stage. 3 P4)
“我们最新的研究成果《毒药研究方案》被可恶的辛迪加间谍偷走了!”作为拉文霍德的一员,你一定
感到很震惊,因为它是我们最尖端的科研人员的一年的研究成果。被辛迪加获得,我们可能会有灭顶之灾。
狡猾的辛迪加为了躲避我们的追杀,他们并没有把《毒药研究方案》带回激流堡,而是藏了起来。但是终究
是我们技高一筹,通过购买侏儒的最新研究成果“静电放射探测器”,我们已经发现了他们的藏身之地。原来
他们早就在奥特兰克山脉的地下修建了一个巨大的城市,现在,他们就把《毒药研究方案》放在了城市的最
深处。更好的消息是,我们已经发现了地下城的入口。作为一名出色的盗贼,你要学会以彼之道,还施彼身
——把《毒药研究方案》偷回来。然而辛迪加布置了严密的防御,更糟糕的是,他们从地精购买了电磁监视器。
无论你的潜行技巧有多么高明,只要一接近它,就会出发警报。只有破坏它的供电系统,才能电磁监视器悄
无声息得失效。
现在, “静电放射探测器”已经为我们生成了一张地图,它可以告诉你整个地下城的布局结构,包括每
一个电磁监视器的位置,及其供电装置的位置。辛迪加的地下城可以被描述为一个N * N 的表格,城市的入口
在( 1 , 1 )处,目标《毒药研究方案》在(N,N)处。每个单元格可能是一片空地、一个障碍物、一个辛迪加卫
士、一个电磁监视器、或者一个的供电装置。从入口处开始,每步你只能向上、下、左、右移动到相邻的一个
单元格,不可以停留在原地。你只能进入空地,或者失去供电系统的电磁监视器的位置,或者摧毁供电装置。
你不能移动到障碍物上,也不能进入辛迪加卫士的视线中。辛迪加卫士可以监视自己所在单元格以及上下左右
共五格的位置,而且他们的视线可以重叠。你不能杀死辛迪加卫士,也不能被他们发现。每个电磁监视器的供
电装置可能存在,也可能无法破坏或者根本不存在。一个供电装置也可能会对应零个、一个或多个电磁监视器,
意味着摧毁它,对应的所有电磁监视器都会失效。( 1 , 1 )和(N,N)一定是可以通行的。拉文霍德要求你在执行
任务之前首先给出一个计划书,即要求算出至少一共需要多少步,才能拿到我们的《毒药研究方案》。
【输入格式】
第1行,两个整数N, M。表示地图大小为N
* N,供电装置的数量为 M。
2 - N + 1 行,每行 N 个整数,每个整数 i 可能是 0 - 1 - 2 或者一个正整数。i = 0 表示该位
为一块空地,i =- 1 表示该位置为一个障碍物,i =- 2 表示该位置为一个辛迪加卫士。如果 i是一个属于
[ 1 ,M]的正整数,则表示该位置为一个供电装置,其编号为 i。如果i是一个大于M的正整数,则表示该位置
为一个电磁监视器,它的电力由编号为 i - M的供电装置提供。
【输出格式】
一个整数,为拿到《毒药研究方案》所需的最少的步数。
【样例输入】
6 2
0 0 0 - 2 - 1 2
- 1 0 0 0 - 1 0
- 2 0 0 0 3 3
- 2 0 0 - 1 - 1 4
0 - 1 0 0 - 1 0
1 0 0 0 - 1 0
【样例输出】
24
【样例说明】
地图如下图,S 为入口,T 为目标,黑色的单元格为障碍物。每个 E 表示一个卫兵,(E)为卫兵
的监视范围。K1表示供电装置 1 ,K2表示供电装置 2 。D1表示供电装置为1 的电磁监视器,D2表示供
电装置为 2的电磁监视器。
最优的路线为(
1 , 1 ) →( 1 , 2 ) →( 2 , 2 ) →( 2 , 3 ) →( 3 , 3 ) →( 4 , 3 ) →( 5 , 3 ) →( 6 , 3 ) →( 6 , 2 )
→( 6 , 1 )(破坏供电1) →( 6 , 2 ) →( 6 , 3 ) →( 5 , 3 ) →( 4 , 3 ) →( 3 , 3 ) →( 3 , 4 ) →( 3 , 5 ) →( 3 , 6
→( 2 , 6 ) →( 1 , 6 )(破坏供电 2 ) →( 2 , 6 ) →( 3 , 6 ) →( 4.6 ) →( 5 , 6 ) →( 6 , 6 )
【Nov 11 P4,分层BFS】潜入辛迪加
【数据规模】
1 <= N <= 50
0 <= M <= 16

 

 

      这是一道钥匙开门类的搜索题,大体思路是把记录数组多开一维空间记录找到某个的钥匙时的状态,然后以拿到某几种钥匙为一层进行BFS。这时可以使用位运算对钥匙进行Hash求解。

      注意对各种障碍物的处理。如果是士兵则上下左右四个方向都要标记。

 

参考代码:

 

program syndicate;

  const

    dx:array[1..4]of integer=(0,0,-1,1);

    dy:array[1..4]of integer=(1,-1,0,0);

  type l=record

    x,y,dist:integer;

    ft:array[1..16]of boolean;

  end;

  var

    map:array[-1..51,-1..51]of integer;

    ff:array[1..16]of boolean;

    v:array[0..100000,0..50,0..50]of boolean;  //三维的标记数组

    n,m,i,j:longint;

    f,s,xx,yy:longint;

    d:array[1..1000000]of l;

    k:longint;

  begin

    readln(n,m);

    for i:=1 to n do

      for j:=1 to n do

        begin

          read(k);

          if k=-2 then  //处理士兵

            begin

              map[i,j]:=-2;

              map[i+1,j]:=-2;

              map[i-1,j]:=-2;

              map[i,j-1]:=-2;

              map[i,j+1]:=-2;

            end;

          if map[i,j]<>-2 then map[i,j]:=k;

        end;

    f:=1;

    s:=1;

    d[1].x:=1;

    d[1].y:=1;

    fillchar(v,sizeof(v),false);

    v[0,1,1]:=true;

    while f<=s do

      begin

        for i:=1 to 4 do

          begin

            xx:=d[f].x+dx[i];

            yy:=d[f].y+dy[i];

            k:=0;

            for j:=1 to m do

              begin

                ff[j]:=d[f].ft[j];

                if ff[j] then k:=k+1<<(j-1);  //位运算记录钥匙

              end;

            if(xx>0)and(xx<=n)and(yy>0)and(yy<=n)then

              begin

                if(map[xx,yy]>0)and(map[xx,yy]<=m) then

                  if not v[k,xx,yy] then

                    begin

                      v[k,xx,yy]:=true;

                      inc(s);

                      k:=k+1<<(map[xx,yy]-1);

                      if s>1000000 then s:=1;

                      ff[map[xx,yy]]:=true;

                      d[s].ft:=ff;

                      d[s].dist:=d[f].dist+1;

                      d[s].x:=xx;

                      d[s].y:=yy;

                      v[k,xx,yy]:=true;

                    end;

                if map[xx,yy]>m then

                  if(ff[map[xx,yy]-m])and(not v[k,xx,yy])then

                    begin

                      v[k,xx,yy]:=true;

                      inc(s);

                      if s>1000000 then s:=1;

                      d[s].ft:=ff;

                      d[s].dist:=d[f].dist+1;

                      d[s].x:=xx;

                      d[s].y:=yy;

                    end;

                if map[xx,yy]=0 then

                  if not v[k,xx,yy] then

                    begin

                      v[k,xx,yy]:=true;

                      inc(s);

                      if s>1000000 then s:=1;

                      d[s].ft:=ff;

                      d[s].dist:=d[f].dist+1;

                      d[s].x:=xx;

                      d[s].y:=yy;

                    end;

                if(xx=n)and(yy=n)then

                  begin

                    writeln(d[s].dist);

                    close(input);

                    close(output);

                    halt;

                  end;

              end;

          end;

        inc(f);

        if f>1000000 then f:=1;

      end;

    writeln('http://www.cnblogs.com/saltless');

  end.

 

本文地址:http://www.cnblogs.com/saltless/archive/2010/11/15/1877353.html

(saltless原创,转载请注明出处)

你可能感兴趣的:(bfs)