5781. 【NOIP提高A组模拟2018.8.8】秘密通道

Description
有一副n*m的地图,有n*m块地,每块是下列四种中的一种:
墙:用#表示,墙有4个面,分别是前面,后面,左面,右面。
起点:用C表示,为主角的起点,是一片空地。
终点:用F表示,为主角的目的地,是一片空地。
空地:用 . 表示。
其中除了墙不能穿过,其他地方都能走。
主角有以下3种操作:
1.移动到相邻的前后左右的地方,花费一个单位时间。
2.向前后左右其中一个方向发射子弹,子弹沿直线穿过,打在最近的一堵墙的一面,然后墙的这面就会形成一个开口通往秘密通道。同一时间最多只能有两个开口,若出现有3个开口,出现时间最早的开口会立即消失。该操作不用时间。
3.可以从一个与开口相邻的空地跳进去,进入秘密通道,从另外一个开口正对的空地跳出来。这个过程花费一个单位时间。
地图四周都是墙,问主角最少用多少时间从C走到F。C和F 只会出现一次。
 
 
Input
第一行输入两个正整数n,m。
接下来n行,每行m个字符描述地图。
 
 
Output
输出1个整数,表示最短时间完成路途。如果无解输出nemoguce
 
 
Solutions

这道题目可以用最短路来做。

我们首先可以预处理出每一个格子向上下左右第一堵 墙在哪。

这个时间复杂度是 O(n^2)的。

两种连边。

第一种就是每一个格子向他周围四个方向连一条长度 为 1 的边。

第二种就是每一个格子向他上下左右的第一堵墙连一 条长度为格子与最近的墙距离的边。

从 C 到 F 求一遍最短路即可。 假如不存在路径,就输出 nemoguce。

 

代码

 

  1 type
  2   arr=record
  3     x,y,w,next:longint;
  4   end;
  5 var
  6   n,m,nm,qq,zz,ll:longint;
  7   b:array [0..501,0..501] of longint;
  8   st:array [0..501,0..501] of char;
  9   a:array [0..5000001] of arr;
 10   ls,d,v,list:array [0..1000001] of longint;
 11 function min(o,p:longint):longint;
 12 begin
 13   if o<p then exit(o);
 14   exit(p);
 15 end;
 16 
 17 procedure add(x,y,z:longint);
 18 begin
 19   inc(nm);
 20   a[nm].x:=x; a[nm].y:=y; a[nm].w:=z;
 21   a[nm].next:=ls[x]; ls[x]:=nm;
 22 end;
 23 
 24 procedure init;
 25 var
 26   i,j,k,mi:longint;
 27   x1,x2,x3,x4,y1,y2,y3,y4:longint;
 28 begin
 29   readln(n,m);
 30   nm:=0; ll:=0;
 31   for i:=1 to n do
 32     begin
 33       for j:=1 to m do
 34         begin
 35           read(st[i,j]);
 36           if st[i,j]<>'#' then
 37             begin
 38               inc(ll);
 39               b[i,j]:=ll;
 40               if st[i,j]='C' then qq:=ll;
 41               if st[i,j]='F' then zz:=ll;
 42             end;
 43         end;
 44       readln;
 45     end;
 46   for i:=1 to n do
 47     for j:=1 to m do
 48       if st[i,j]<>'#' then
 49         begin
 50           if st[i-1,j]<>'#' then add(b[i,j],b[i-1,j],1);
 51           if st[i+1,j]<>'#' then add(b[i,j],b[i+1,j],1);
 52           if st[i,j-1]<>'#' then add(b[i,j],b[i,j-1],1);
 53           if st[i,j+1]<>'#' then add(b[i,j],b[i,j+1],1);
 54           x1:=i; x2:=i; x3:=i; x4:=i;
 55           y1:=j; y2:=j; y3:=j; y4:=j;
 56           while st[x1-1,y1]<>'#' do dec(x1);
 57           while st[x2+1,y2]<>'#' do inc(x2);
 58           while st[x3,y3-1]<>'#' do dec(y3);
 59           while st[x4,y4+1]<>'#' do inc(y4);
 60           mi:=min(min(min(y4-j,j-y3),x2-i),i-x1)+1;
 61           if (x1<>i) and (x1<>i-1) then add(b[i,j],b[x1,y1],min(mi,i-x1));
 62           if (x2<>i) and (x2<>i+1) then add(b[i,j],b[x2,y2],min(mi,x2-i));
 63           if (y3<>j) and (y3<>j-1) then add(b[i,j],b[x3,y3],min(mi,j-y3));
 64           if (y4<>j) and (y4<>j+1) then add(b[i,j],b[x4,y4],min(mi,y4-j));
 65         end;
 66 end;
 67 
 68 procedure spfa;
 69 var
 70   i,h,t:longint;
 71 begin
 72   fillchar(d,sizeof(d),63);
 73   fillchar(v,sizeof(v),0);
 74   fillchar(list,sizeof(list),0);
 75   h:=0; t:=1;
 76   d[qq]:=0; v[qq]:=1; list[1]:=qq;
 77   repeat
 78     inc(h);
 79     i:=ls[list[h]];
 80     while i<>0 do
 81       with a[i] do
 82         begin
 83           if d[x]+w<d[y] then
 84             begin
 85               d[y]:=d[x]+w;
 86               if v[y]=0 then
 87                 begin
 88                   v[y]:=1;
 89                   inc(t);
 90                   list[t]:=y;
 91                 end;
 92             end;
 93           i:=next;
 94         end;
 95     v[list[h]]:=0;
 96   until h=t;
 97 end;
 98 
 99 begin
100   assign(input,'portal.in');
101   assign(output,'portal.out');
102   reset(input);
103   rewrite(output);
104   init;
105   spfa;
106   if d[zz]=d[0] then writeln('nemoguce')
107                 else writeln(d[zz]);
108   close(input);
109   close(output);
110 end.

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值