这进度 唉…… 毕竟中间停了大概一年

题目来源:http://www.nocow.cn/index.php/Translate:USACO/maze1

1.找到两个出口 (不多说)

2.一遍SPFA,分别计算从两个出口到任意一个不是'+'或者'-'

  或者'|'的地方   (即不是栅栏)

3.根据一遍SPFA数组中dis1[i,j]表示从(i,j)到出口1的最短距离

                    dis2[i,j]表示从(i,j)到出口2的最短距离

 

  至于为什么 (百度“SPFA”) 

 

这道题彻底写囧了,

第一遍想到SPFA,执行了n*m遍SPFA,数组没开好,TLE

第二遍改进数组,改大了,MLE

第三遍甚至有改写成dijkstra+heap用堆优化dijkstra的冲动

第四遍突然领悟SPFA不断松弛  不断入队出队的实质

即计算点st到en的最短距离时

dis[i]保存从st到i的最短距离

     不断更新dis[i]最后更新到dis[en]

即计算出st到en的最短距离

 

而现在需要计算从出口到任意一个点的最短距离不就是这么回事吗?

反过来,把出口当做起点,

一切迎刃而解、

 

AC (时间还算客观)

后来看nocow官方题解,说BFS floodfill就可以了 后来想想貌似可以

这道题这样看貌似太弱了、

 

贴SPFA版代码,dijkstra+heap==再说

 

恶心了点。。。

{
ID: xiaweiy1
PROG: maze1
LANG: PASCAL
}
const dx:array[1..4]of longint=(-1,0,0,1);
      dy:array[1..4]of longint=(0,-1,1,0);
      maxn=201; maxm=80; maxx=100000;
var i,j,n,m,fmax,fmin,k,l,u,tmp,cnt:longint;
    map:array[1..maxn,1..maxm]of char;
    app,obt,loc:array[1..maxn,1..maxm]of longint;
    done:boolean;
    opp:array[1..maxn*maxm,1..2]of longint;
    que:array[1..maxx]of longint;
    mark:array[1..maxn*maxm]of boolean;
    dis,dis1,dis2:array[1..maxn*maxm]of longint;
    spe:array[1..2,1..2]of longint;
function min(x,y:longint):longint;
begin
if x<y then exit(x) else exit(y);
end;
function check(a,b,c,d:longint):boolean;
begin
if (obt[a,b]<>1)and(obt[c,d]<>1) then exit(true) else exit(false);
end;
function spfa(st,en,cho:longint):longint;
var i,now,tail,head,nx,ny,tx,ty:longint;
begin
fillchar(que,sizeof(que),0);
fillchar(mark,sizeof(mark),false);
for i:=1 to n*m do dis[i]:=maxlongint;
dis[st]:=0;  mark[st]:=true;  que[1]:=st;
tail:=1; head:=1;
while tail<=head do
   begin
   now:=que[tail];
   nx:=opp[now,1]; ny:=opp[now,2];
   for i:=1 to 4 do
       begin
       tx:=nx+dx[i]; ty:=ny+dy[i];
       if (tx>=1)and(tx<=n)and(ty>=1)and(ty<=m) then
          begin
          if check(nx,ny,tx,ty) then
             begin
             if (dis[now]<>maxlongint)and(dis[now]+1<dis[loc[tx,ty]]) then
                begin
                dis[loc[tx,ty]]:=dis[now]+1;
                if not mark[loc[tx,ty]] then
                   begin
                   inc(head);
                   que[head]:=loc[tx,ty];
                   mark[loc[tx,ty]]:=true;
                   end;
                end;
             end;
          end;
       end;
   mark[now]:=false;
   inc(tail);
   end;
if cho=1 then dis1:=dis else dis2:=dis;
exit((dis[en]+1) div 2);
end;
begin
assign(input,'maze1.in');
reset(input);
assign(output,'maze1.out');
rewrite(output);
readln(m,n);
n:=2*n+1;
m:=2*m+1;
for i:=1 to n do
    begin
    for j:=1 to m do
        begin
        read(map[i,j]);
        if (map[i,j]='+')or(map[i,j]='-')or(map[i,j]='|') then
           obt[i,j]:=1;        //obstacle  It means here is a fence.
        loc[i,j]:=(i-1)*m+j;   // index use number to hash the location (i,j)
        opp[(i-1)*m+j,1]:=i; opp[(i-1)*m+j,2]:=j;
        end;
    readln;
    end;
for i:=1 to n  do
    begin
    if map[i,1]=' ' then begin inc(cnt); spe[cnt,1]:=i; spe[cnt,2]:=1; end;
    if map[i,m]=' ' then begin inc(cnt); spe[cnt,1]:=i; spe[cnt,2]:=m; end;
    end;
for i:=1 to m do
    begin
    if map[1,i]=' ' then begin inc(cnt); app[1,i]:=1; spe[cnt,1]:=1; spe[cnt,2]:=i; end;
    if map[n,i]=' ' then begin inc(cnt); app[n,i]:=1; spe[cnt,1]:=n; spe[cnt,2]:=i; end;
    end;                       //The aim is to find two exits;
fmax:=0;
done:=false;
for i:=1 to n do
    begin
    for j:=1 to m do
        begin
        if (obt[i,j]<>1)and(app[i,j]<>1) then    //not a fence
           begin
           if not done then
              begin
              fmin:=maxlongint;
              for k:=1 to 2 do
                  begin
                  tmp:=spfa(loc[spe[k,1],spe[k,2]],loc[i,j],k);
                  if tmp<fmin then
                     fmin:=tmp;
                  end;
              done:=true;
              if fmin>fmax then
                 fmax:=fmin;
              end
           else begin
                tmp:=min(dis1[loc[i,j]],dis2[loc[i,j]])+1;
                tmp:=tmp div 2;
                if tmp>fmax then fmax:=tmp;
                end;
           end;
        end;

    end;
writeln(fmax);
close(input);
close(output);
end.
posted on 2011-02-12 23:03  Dimfouasstrawberry  阅读(196)  评论(0)    收藏  举报