jzoj3243. Cube

Description

你被困在一个密室里。经过一轮摸索,你在密室里有所发现:
1.密室是一个呈m×n网格的长方形,地面有六个格子被上了色;
2.密室地面部分格子可能有障碍物;
3.密室的某一格有一个六面都没上色的立方体;
4.当立方体滚动到相邻无障碍物的格子,如果立方体接触地面的一面没有颜色而地面有颜色,则该颜色会从地面转移到立方体上;如果立方体接触地面的一面有颜色而地面没有颜色,则该颜色会从立方体转移到地面上;如果立方体接触地面的一面和地面都有颜色,则两者的颜色都不会转移。
5.当立方体滚动到密室的指定地点,如果立方体六面都被涂上了颜色,则传送门就会开启,让你逃离这个密室。
由于时间紧迫,你必须借助计算机的力量,算出立方体最少滚动几次就可以让你逃离这个密室。

Input

输入的第一行是用空格分隔的两个正整数m和n(2<=m<=20,2<=n<=20),分别代表密室的高和宽。接下来的m行,每行有n个字符,含义如下:
‘.’:该格子是空白的;
‘#’:该格子有障碍物;
‘P’:该格子是上色的;
‘C’:立方体就在这个格子;
‘G’:能让你逃离密室的指定地点。
整个密室保证正好有6个格子是‘P’,1个格子是‘C’,1个格子是‘G’,‘.’的格子不超过12个。

Output

输出仅一个整数,代表立方体最少滚动的次数。我们保证每个密室场景都有解。
对以下第一个样例,立方体最少只需要滚动10次(下右右上右右下左右左)。

Sample Input

输入1:
2 5
C.PPP
PPPG.

输入2:
4 5
C…
G##.P
.##PP
…PPP

输入3:
3 3
PPP
PCP
PG.

输入4:
2 10
.PPPCPPP…
…G…

Sample Output

输出1:
10

输出2:
23

输出3:
15

输出4:
21

Data Constraint

2<=m<=20,2<=n<=20

题解

首先,这题n和m及其的小。而且可以走的点也最多只有20.
想到什么?暴力!
我们分析一下状态数。
由于6种颜色只会在20个格子中出现或在方块上出现,所以方案数为C266C_{26}^6
然后方块能在20个格子的任意位置,方案数为2020
乘起来就是46046004604600
不会很大。
直接暴力搞即可。
然而在暴力的时候可能要在转移的时候出现常数。
导致我这个sb·pascal过不去。
直接上双向广搜。

标程

type
        new=record
                cr,pr,x,y,step:longint;
        end;
var
        i,j,k,l,n,m,gs,sx,sy,ex,ey,head,tail,took,head1,tail1,took1:longint;
        kw:array[1..20,1..2] of longint;
        map:array[1..20,1..20] of char;
        id:array[1..20,1..20 ] of longint;
        a,b:array[1..1500000] of new;
        fx:array[1..4,1..2] of longint=((-1,0),(1,0),(0,-1),(0,1));
        hs,hs1:array[1..1500007] of longint;
        jl,jl1:array[1..1500007] of new;
        mo:longint=1500007;
function kk(x,y:new):boolean;
begin
        if (x.x<>y.x) or (x.y<>y.y) or (x.cr<>y.cr) or (x.pr<>y.pr) then exit(false);
        exit(true);
end;
function find1(x:longint;now:new):longint;
var
        i:longint;
begin
        i:=x;
        while (hs1[i]>0) and (not kk(jl1[i],now)) do
        begin
                inc(i);
                if i>mo then i:=1;
        end;
        exit(i);
end;
procedure insert1(x,y:longint;now:new);
begin
        hs1[x]:=y;jl1[x]:=now;
end;
function find(x:longint;now:new):longint;
var
        i:longint;
begin
        i:=x;
        while (hs[i]>0) and (not kk(jl[i],now)) do
        begin
                inc(i);
                if i>mo then i:=1;
        end;
        exit(i);
end;
procedure insert(x,y:longint;now:new);
begin
        hs[x]:=y;jl[x]:=now;
end;
procedure bfsd(dep:longint);
var
        i,j,k,nx,ny,jx,jy:longint;
        l:int64;
        c,jlc:array[1..6] of longint;
        hy,jlhy:array[1..20,1..20] of longint;
        pd:new;
begin
        j:=b[dep].cr;
        for i:=6 downto 1 do
        begin
                c[i]:=j mod 2;
                j:=j div 2;
        end;
        fillchar(hy,sizeof(hy),0);
        j:=b[dep].pr;
        for i:=gs downto 1 do
        begin
                hy[kw[i,1],kw[i,2]]:=j mod 2;
                j:=j div 2;
        end;
        if dep=4 then
        i:=i;
        jlc:=c;jlhy:=hy;
        for i:=1 to 4 do
        begin
                nx:=b[dep].x+fx[i,1];
                ny:=b[dep].y+fx[i,2];
                if (nx>0) and (ny>0) and (nx<=n) and (ny<=m) then
                begin
                        if map[nx,ny]<>'#' then
                        begin
                                c:=jlc;
                                hy:=jlhy;
                                if (hy[b[dep].x,b[dep].y]=1) and (c[5]=0) then
                                begin
                                        c[5]:=1;
                                        hy[b[dep].x,b[dep].y]:=0;
                                end
                                else
                                if (hy[b[dep].x,b[dep].y]=0) and (c[5]=1) then
                                begin
                                        c[5]:=0;
                                        hy[b[dep].x,b[dep].y]:=1;
                                end;
                                if i=3 then
                                begin
                                        j:=c[5];c[5]:=c[2];c[2]:=c[3];c[3]:=c[4];c[4]:=j;
                                end;
                                if i=4 then
                                begin
                                        j:=c[5];c[5]:=c[4];c[4]:=c[3];c[3]:=c[2];c[2]:=j;
                                end;
                                if i=1 then
                                begin
                                        j:=c[5];c[5]:=c[1];c[1]:=c[3];c[3]:=c[6];c[6]:=j;
                                end;
                                if i=2 then
                                begin
                                        j:=c[5];c[5]:=c[6];c[6]:=c[3];c[3]:=c[1];c[1]:=j;
                                end;
                                k:=0;
                                for j:=1 to 6 do k:=k*2+c[j];
                                jx:=k;
                                k:=0;
                                for j:=1 to gs do
                                begin
                                        k:=k*2+hy[kw[j,1],kw[j,2]];
                                end;
                                jy:=k;
                                pd.x:=nx;pd.y:=ny;pd.step:=b[dep].step;pd.cr:=jx;pd.pr:=jy;
                                l:=(jx*1007+jy*107+ny*10007+nx*100007) mod mo;
                                k:=find1(l,pd);
                                if hs1[k]=0 then
                                begin
                                        inc(took1);
                                        insert1(k,took1,pd);
                                        b[took1].x:=nx;b[took1].y:=ny;b[took1].step:=b[dep].step+1;b[took1].cr:=jx;b[took1].pr:=jy;
                                        k:=find(l,pd);
                                        if hs[k]>0 then
                                        begin
                                                writeln(a[hs[k]].step+b[took1].step);
                                                halt;
                                        end;
                                end;
                        end;
                end;
        end;
end;
procedure bfs(dep:longint);
var
        i,j,k,nx,ny,jx,jy:longint;
        l:int64;
        c,jlc:array[1..6] of longint;
        hy,jlhy:array[1..20,1..20] of longint;
        pd:new;
begin
        j:=a[dep].cr;
        for i:=6 downto 1 do
        begin
                c[i]:=j mod 2;
                j:=j div 2;
        end;
        fillchar(hy,sizeof(hy),0);
        j:=a[dep].pr;
        for i:=gs downto 1 do
        begin
                hy[kw[i,1],kw[i,2]]:=j mod 2;
                j:=j div 2;
        end;
        jlc:=c;jlhy:=hy;
        for i:=1 to 4 do
        begin
                nx:=a[dep].x+fx[i,1];
                ny:=a[dep].y+fx[i,2];
                if (nx>0) and (ny>0) and (nx<=n) and (ny<=m) then
                begin
                        if map[nx,ny]<>'#' then
                        begin
                                c:=jlc;
                                hy:=jlhy;
                                if i=3 then
                                begin
                                        j:=c[5];c[5]:=c[2];c[2]:=c[3];c[3]:=c[4];c[4]:=j;
                                end;
                                if i=4 then
                                begin
                                        j:=c[5];c[5]:=c[4];c[4]:=c[3];c[3]:=c[2];c[2]:=j;
                                end;
                                if i=1 then
                                begin
                                        j:=c[5];c[5]:=c[1];c[1]:=c[3];c[3]:=c[6];c[6]:=j;
                                end;
                                if i=2 then
                                begin
                                        j:=c[5];c[5]:=c[6];c[6]:=c[3];c[3]:=c[1];c[1]:=j;
                                end;
                                if (hy[nx,ny]=1) and (c[5]=0) then
                                begin
                                        c[5]:=1;
                                        hy[nx,ny]:=0;
                                end
                                else
                                if (hy[nx,ny]=0) and (c[5]=1) then
                                begin
                                        c[5]:=0;
                                        hy[nx,ny]:=1;
                                end;
                                k:=0;
                                for j:=1 to 6 do k:=k*2+c[j];
                                jx:=k;
                                k:=0;
                                for j:=1 to gs do
                                begin
                                        k:=k*2+hy[kw[j,1],kw[j,2]];
                                end;
                                jy:=k;
                                pd.x:=nx;pd.y:=ny;pd.step:=a[dep].step;pd.cr:=jx;pd.pr:=jy;
                                l:=(jx*1007+jy*107+ny*10007+nx*100007) mod mo;
                                k:=find(l,pd);
                                if hs[k]=0 then
                                begin
                                        inc(took);
                                        insert(k,took,pd);
                                        a[took].x:=nx;a[took].y:=ny;a[took].step:=a[dep].step+1;a[took].cr:=jx;a[took].pr:=jy;
                                        k:=find1(l,pd);
                                        if hs1[k]>0 then
                                        begin
                                                writeln(b[hs1[k]].step+a[took].step);
                                                halt;
                                        end;
                                end;
                        end;
                end;
        end;
end;
begin
        //assign(input,'0data.in');reset(input);
        readln(n,m);
        for i:=1 to n do
        begin
                for j:=1 to m do
                begin
                        read(map[i,j]);
                        if map[i,j]<>'#' then
                        begin
                                inc(gs);
                                kw[gs,1]:=i;
                                kw[gs,2]:=j;
                                id[i,j]:=gs;
                        end;
                        if map[i,j]='C' then
                        begin
                                map[i,j]:='.';
                                sx:=i;sy:=j;
                        end;
                        if map[i,j]='G' then
                        begin
                                map[i,j]:='.';
                                ex:=i;ey:=j;
                        end;
                end;
                readln;
        end;
        head:=1;tail:=1;took:=1;
        head1:=1;tail1:=1;took1:=1;
        b[1].x:=ex;b[1].y:=ey;
        a[1].x:=sx;a[1].y:=sy;
        l:=0;
        for i:=1 to gs do
        begin
                l:=l*2;
                if map[kw[i,1],kw[i,2]]='P' then l:=l+1;
        end;
        a[1].pr:=l;
        b[1].cr:=63;
        l:=(a[1].cr*1007+a[1].pr*107+a[1].y*10007+a[1].x*100007) mod mo;
        k:=find(l,a[1]);
        insert(k,1,a[1]);
        l:=(b[1].cr*1007+b[1].pr*107+b[1].y*10007+b[1].x*100007) mod mo;
        k:=find1(l,b[1]);
        insert1(k,1,b[1]);
        repeat
                for i:=head to tail do
                begin
                        bfs(i);
                end;
                head:=tail+1;
                tail:=took;
                for i:=head1 to tail1 do
                begin
                        bfsd(i);
                end;
                head1:=tail1+1;
                tail1:=took1;
        until (head>tail) or (head1>tail1);
end.


巨长的代码。

原文地址:https://www.cnblogs.com/RainbowCrown/p/11148351.html