码迷,mamicode.com
首页 > 其他好文 > 详细

[noip2013][codevs3290]华容道 bfs+spfa

时间:2015-09-11 22:12:03      阅读:479      评论:0      收藏:0      [点我收藏+]

标签:

const
        u:array[1..4] of integer=(-1,0,1,0);
        v:array[1..4] of integer=(0,1,0,-1);
        oo=100000000;
type node=record
      x,y,cs,l:longint;
      end;


var
        ft:text;
        n,m,q,ii,i,i1,j1,j,l,w,x,y,x1,y1,x2,y2,x3,y3,es,ey,wei,tou,kx,ky,ans:longint;
        r:array[0..5000000] of node;
        aa,a,fb,fb2:array[0..31,0..31] of longint;
        ff,z,z2:array[0..31,0..31,1..4] of longint;
        f:array[0..31,0..31,1..4,1..4] of longint;

        procedure bfs(x,y:longint);
        var i,x1,y1:longint;
        begin
                wei:=1;
                tou:=0;
                r[wei].x:=x;
                r[wei].y:=y;
                r[wei].cs:=fb[x,y];
                while tou<wei do
                begin
                        inc(tou);
                        for i:=1 to 4 do
                        begin
                                x1:=r[tou].x+u[i];
                                y1:=r[tou].y+v[i];
                                if (a[x1,y1]=1)and(r[tou].cs+1<fb[x1,y1]) then
                                begin
                                        inc(wei);
                                        r[wei].x:=x1;
                                        r[wei].y:=y1;
                                        r[wei].cs:=r[tou].cs+1;
                                        fb[x1,y1]:=r[wei].cs;
                                end;
                        end;
                end;
        end;

        begin
                readln(n,m,q);
                for i:=1 to n do
                begin
                        for j:=1 to m do
                        read(a[i,j]);
                        readln;
                end;

                aa:=a;
                for i:=1 to n do
                for j:=1 to m do
                begin
                        fb2[i,j]:=oo;
                        for l:=1 to 4 do
                        begin
                                z2[i,j,l]:=oo;
                                for w:=1 to 4 do f[i,j,l,w]:=oo;
                        end;
                end;

                for i:=1 to n do
                for j:=1 to m do
                if a[i,j]=1 then
                for l:=1 to 4 do
                begin
                        x:=i+u[l];
                        y:=j+v[l];
                        if (x>0)and(x<n+1)and(y>0)and(y<m+1)and(a[x,y]=1) then
                        begin
                                a[x,y]:=0;
                                fb:=fb2;
                                fb[i,j]:=1;
                                bfs(i,j);
                                for w:=1 to 4 do
                                begin
                                        x1:=x+u[w];
                                        y1:=y+v[w];
                                        if (x1>0)and(x1<n+1)and(y1>0)and(y1<m+1)and(fb[x1,y1]<oo) then
                                        begin
                                                f[i,j,l,w]:=fb[x1,y1];
                                        end;
                                end;
                                a[x,y]:=1;
                        end;
                end;

        for ii:=1 to q do
        begin
                read(kx,ky,x,y,es,ey);
                if (x=es)and(y=ey) then
                begin
                        writeln(0);
                        continue;
                end;
                fb:=fb2;
                a[x,y]:=0;
                fb[kx,ky]:=0;
                bfs(kx,ky);
                wei:=0;
                z:=z2;
                fillchar(ff,sizeof(ff),0);
                for j:=1 to 4 do
                begin
                        x1:=x+u[j];
                        y1:=y+v[j];
                        if (x1>0)and(x1<n+1)and(y1>0)and(y1<m+1)and(fb[x1,y1]<oo) then
                        begin
                        inc(wei);
                        r[wei].x:=x;
                        r[wei].y:=y;
                        r[wei].l:=j;
                        z[x,y,j]:=fb[x1,y1];
                        ff[x,y,j]:=1;
                        end;
                end;

                tou:=0;
                while tou<wei do
                begin
                        inc(tou);
                        for i:=1 to 4 do
                        begin
                        x2:=r[tou].x;
                        y2:=r[tou].y;
                        x1:=x2+u[r[tou].l]+u[i];
                        y1:=y2+v[r[tou].l]+v[i];
                        x3:=x2+u[r[tou].l];
                        y3:=y2+v[r[tou].l];
                        if (f[x2,y2,r[tou].l,i]<>oo)and(z[x3,y3,i]>z[x2,y2,r[tou].l]+f[x2,y2,r[tou].l,i]) then
                        begin
                                z[x3,y3,i]:=z[x2,y2,r[tou].l]+f[x2,y2,r[tou].l,i];
                                if ff[x3,y3,i]=0 then
                                begin
                                ff[x3,y3,i]:=1;
                                inc(wei);
                                r[wei].x:=x3;
                                r[wei].y:=y3;
                                r[wei].l:=i;
                                end;
                        end;
                        end;

                        ff[r[tou].x,r[tou].y,r[tou].l]:=0;
                end;

                ans:=oo;
                for i:=1 to 4 do
                if z[es,ey,i]<ans then ans:=z[es,ey,i];
                if ans=oo then writeln(-1)
                else writeln(ans);
                a[x,y]:=1;
                end;
        end.

因为对棋子的移动最终对应着对空格的移动,而空格的初始位置(非起始情况)一定是在目标棋子的上下左右的。

这样我们把空格先准备好,然后移动一下棋子,这种操作的代价很容易发现是常数。因此可以使用最短路。方法是把每个棋子一分为四,上下左右,[一个棋 子的左边]就代表了空格的初始位置在这个棋子的左边,即它前一次是从左边移过来的。每个棋子的每一边可以建立于上面棋子的下边,下面棋子的上边等的联系 (用一个有向图来存储),并存储价值。

最后还有一个小问题,就是每次的q的空白位置不是在目标棋子的上下左右。这时候选择目标棋子的一类,并且修改其与周遭棋子联系的边权,然后做最短路,然后记得要改回去。

[noip2013][codevs3290]华容道 bfs+spfa

标签:

原文地址:http://www.cnblogs.com/victorslave/p/4802135.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!