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个格子中出现或在方块上出现,所以方案数为
然后方块能在20个格子的任意位置,方案数为
乘起来就是
不会很大。
直接暴力搞即可。
然而在暴力的时候可能要在转移的时候出现常数。
导致我这个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.
巨长的代码。