火星移民(mars)
【问题描述】
在2xyz 年,人类已经移民到了火星上。由于工业的需要,人们开始在火星
上采矿。火星的矿区是一个边长为N 的正六边形,为了方便规划,整个矿区被分
为6*N*N 个正三角形的区域(如图1)。
整个矿区中存在A 矿,B 矿,C 矿三个矿场,和a 厂,b 厂,c 厂三个炼矿厂。
每个三角形的区域可以是一个矿场、炼矿厂、山地、或者平地。现在矿区管理局
要求建立一个交通系统,使得矿场和对应炼矿厂之间存在一条公路,并且三条公
路互不交叉(即一个三角形区域中不存在两条以上运输不同矿的公路)。两个三角
形区域是相邻的当且仅当这两个三角形存在公共边,只有相邻的两个区域之间才
能建一段路,建这段路的费用为1。注意,山地上是不能建公路的。由于火星金
融危机的影响,矿区管理局想知道建立这样一个交通系统最少要花多少费用。更
多的,当局向知道有多少种花费最小的方案。
【输入格式】
第1 行一个整数N。表示这个矿区是边长为N 的正六边形。
接下来有6*N*N 的整数,分为2*N 行,表示矿区当前区域的情况。0 表示平
地,1,2,3 表示对应的矿区或者或者炼矿厂,4 表示山地。(样例1 对应图2)。可能
有多组数据,请处理到文件结尾
【输出格式】
对于每组数据,包含两个整数,表示最小费用和达到最小费用的方案数。如
果找不到符合要求的方案,输出-1 -1。由于方案数可能过大,所以请把方案数
mod 1000000007。
【样例输入1】
2
0 1 0 0 0
0 0 2 0 4 0 0
0 0 4 3 0 3 2
0 0 0 1 0
【样例输出1】
18 1
【样例输入2】
3
0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0
0 0 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 3 0 0 0 0
0 0 0 0 0 0 0 0 0
0 3 0 1 0 2 0
【样例输出2】
44 1
【数据规模和约定】
对于50%的数据,N≤4
对于100%的数据,N≤6
插头dp
将两个相邻的三角形合并成一个平行四边形来处理,用一个4进制数表示插头状况
0表示没有插头,1表示1号插头,2表示2号插头,3表示3号插头
四进制数比较多,但状态比较少,存储的时候用hash即可,一个好的hash方程是十分重要的,如果重复了就死循环了
转移十分的长
program mars;
const
maxn=500000;
lim=1000000007;
var
q,p,plus,status,x,y,o,n,i,j,k,l:longint;
four:array [0..31] of int64;
dl,f,c:array [0..1,0..maxn] of longint;
rehash:array [0..1,0..maxn] of longint;
yes:array [0..1,0..maxn] of boolean;
tot:array [0..1] of longint;
map:array [0..30,0..30] of longint;
function hash (o,now:longint):longint;inline;
var
i:int64;
begin
i:=now mod maxn + 2;
repeat
inc(i);
if i>maxn then i:=i-maxn;
until (not yes[o][i])or((yes[o][i])and(rehash[o][i]=now));
yes[o][i]:=true;
rehash[o][i]:=now;
exit(i);
end;
procedure push (o,status,point,way:longint);inline;
var
i:longint;
begin
i:=hash(o,status);
if (c[o,i]>0)and(f[o,i]<point) then exit;
if c[o,i]=0 then
begin
inc(tot[o]);
dl[o,tot[o]]:=status;
end;
if (c[o,i]>0)and(f[o,i]>point) then c[o,i]:=0;
f[o,i]:=point;
c[o,i]:=c[o,i]+way;
if c[o,i]>=lim then c[o,i]:=c[o,i]-lim;
end;
begin
assign(input,'mars.in');
reset(input);
assign(output,'mars.out');
rewrite(output);
four[0]:=1;
for i:=1 to 13 do
four[i]:=four[i-1]*4;
while not seekeof do
begin
read(n);
filldword(map,sizeof(map) div 4,4);
for i:=1 to n do
for j:=1 to (n+i-1)*2+1 do
read(map[i,j]);
for i:=1 to n do
for j:=1 to (2*n-i)*2+1 do
read(map[n+i,j]);
o:=0;
fillchar(f[o],sizeof(f[o]),0);
fillchar(c[o],sizeof(c[o]),0);
fillchar(yes[o],sizeof(yes[o]),false);
tot[o]:=1;
dl[o,1]:=0;
c[o,hash(o,0)]:=1;
for i:=1 to n do
for j:=1 to n+i do
begin
o:=1-o;
tot[o]:=0;
fillchar(f[o],sizeof(f[o]),0);
fillchar(c[o],sizeof(c[o]),0);
fillchar(yes[o],sizeof(yes[o]),false);
for k:=1 to tot[1-o] do
begin
plus:=hash(1-o,dl[1-o,k]);
status:=dl[1-o,k];
if j=1 then status:=status*4;
x:=status div four[j-1] mod 4;
y:=status div four[j] mod 4;
status:=status mod four[j-1] + status div four[j+1] * four[j+1];
if (map[i,j*2-1]=4)and(map[i,j*2]=4) then
if (x<>0)or(y<>0) then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if map[i,j*2-1]=4 then
if x<>0 then continue
else
if map[i,j*2]=0 then
if y=0 then push(o,status,f[1-o,plus],c[1-o,plus])
else push(o,status+four[j]*y,f[1-o,plus]+1,c[1-o,plus])
else
if y=0 then push(o,status+four[j]*map[i,j*2],f[1-o,plus]+1,c[1-o,plus])
else
if y<>map[i,j*2] then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if map[i,j*2]=4 then
if y<>0 then continue
else
if map[i,j*2-1]=0 then
if x=0 then push(o,status,f[1-o,plus],c[1-o,plus])
else push(o,status+four[j-1]*x,f[1-o,plus]+1,c[1-o,plus])
else
if x=0 then push(o,status+four[j-1]*map[i,j*2-1],f[1-o,plus]+1,c[1-o,plus])
else
if x<>map[i,j*2-1] then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if (map[i,j*2-1]=0)and(map[i,j*2]=0) then
if (x=0)and(y=0) then
begin
push(o,status,f[1-o,plus],c[1-o,plus]);
push(o,status+(four[j-1]+four[j])*1,f[1-o,plus]+3,c[1-o,plus]);
push(o,status+(four[j-1]+four[j])*2,f[1-o,plus]+3,c[1-o,plus]);
push(o,status+(four[j-1]+four[j])*3,f[1-o,plus]+3,c[1-o,plus]);
end
else
if x=0 then
begin
push(o,status+four[j]*y,f[1-o,plus]+1,c[1-o,plus]);
push(o,status+four[j-1]*y,f[1-o,plus]+2,c[1-o,plus]);
end
else
if y=0 then
begin
push(o,status+four[j-1]*x,f[1-o,plus]+1,c[1-o,plus]);
push(o,status+four[j]*x,f[1-o,plus]+2,c[1-o,plus]);
end
else
begin
push(o,status+four[j-1]*x+four[j]*y,f[1-o,plus]+2,c[1-o,plus]);
if x=y then push(o,status,f[1-o,plus]+1,c[1-o,plus]);
end
else
if map[i,j*2-1]=0 then
if (x=0)and(y=0) then
begin
push(o,status+four[j-1]*map[i,j*2],f[1-o,plus]+2,c[1-o,plus]);
push(o,status+four[j]*map[i,j*2],f[1-o,plus]+1,c[1-o,plus]);
end
else
if x=0 then
if y<>map[i,j*2] then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if y=0 then
begin
push(o,status+four[j-1]*x+four[j]*map[i,j*2],f[1-o,plus]+2,c[1-o,plus]);
if x=map[i,j*2] then push(o,status,f[1-o,plus]+1,c[1-o,plus]);
end
else
if y<>map[i,j*2] then continue
else push(o,status+four[j-1]*x,f[1-o,plus]+1,c[1-o,plus])
else
if map[i,j*2]=0 then
if (x=0)and(y=0) then
begin
push(o,status+four[j]*map[i,j*2-1],f[1-o,plus]+2,c[1-o,plus]);
push(o,status+four[j-1]*map[i,j*2-1],f[1-o,plus]+1,c[1-o,plus]);
end
else
if x=0 then
begin
push(o,status+four[j-1]*map[i,j*2-1]+four[j]*y,f[1-o,plus]+2,c[1-o,plus]);
if y=map[i,j*2-1] then push(o,status,f[1-o,plus]+1,c[1-o,plus]);
end
else
if y=0 then
if x<>map[i,j*2-1] then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if x<>map[i,j*2-1] then continue
else push(o,status+four[j]*y,f[1-o,plus]+1,c[1-o,plus])
else
if (x=0)and(y=0) then
begin
push(o,status+four[j-1]*map[i,j*2-1]+four[j]*map[i,j*2],f[1-o,plus]+2,c[1-o,plus]);
if map[i,j*2]=map[i,j*2-1] then push(o,status,f[1-o,plus]+1,c[1-o,plus]);
end
else
if x=0 then
if y<>map[i,j*2] then continue
else push(o,status+four[j-1]*map[i,j*2-1],f[1-o,plus]+1,c[1-o,plus])
else
if y=0 then
if x<>map[i,j*2-1] then continue
else push(o,status+four[j]*map[i,j*2],f[1-o,plus]+1,c[1-o,plus])
else
if (x<>map[i,j*2-1])or(y<>map[i,j*2]) then continue
else push(o,status,f[1-o,plus],c[1-o,plus]);
end;
end;
for i:=n+1 to 2*n do
for j:=1 to 3*n+1-i do
begin
l:=3*n+1-i;
o:=1-o;
tot[o]:=0;
fillchar(f[o],sizeof(f[o]),0);
fillchar(c[o],sizeof(c[o]),0);
fillchar(yes[o],sizeof(yes[o]),false);
for k:=1 to tot[1-o] do
begin
plus:=hash(1-o,dl[1-o,k]);
status:=dl[1-o,k];
if (i=n+1)and(j=1) then status:=status*4;
if status div four[l+1] <>0 then continue;
x:=status div four[j-1] mod 4;
y:=status div four[j] mod 4;
status:=status mod four[j-1] + status div four[j+1] * four[j+1];
if (map[i,j*2-2]=4)and(map[i,j*2-1]=4) then
if (x<>0)or(y<>0) then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if map[i,j*2-2]=4 then
if x<>0 then continue
else
if map[i,j*2-1]=0 then
if y=0 then push(o,status,f[1-o,plus],c[1-o,plus])
else push(o,status+four[j]*y,f[1-o,plus]+1,c[1-o,plus])
else
if y=0 then push(o,status+four[j]*map[i,j*2-1],f[1-o,plus]+1,c[1-o,plus])
else
if y<>map[i,j*2-1] then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if map[i,j*2-1]=4 then
if y<>0 then continue
else
if map[i,j*2-2]=0 then
if x=0 then push(o,status,f[1-o,plus],c[1-o,plus])
else push(o,status+four[j-1]*x,f[1-o,plus]+1,c[1-o,plus])
else
if x=0 then push(o,status+four[j-1]*map[i,j*2-2],f[1-o,plus]+1,c[1-o,plus])
else
if x<>map[i,j*2-2] then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if (map[i,j*2-2]=0)and(map[i,j*2-1]=0) then
if (x=0)and(y=0) then
begin
push(o,status,f[1-o,plus],c[1-o,plus]);
push(o,status+(four[j-1]+four[j])*1,f[1-o,plus]+3,c[1-o,plus]);
push(o,status+(four[j-1]+four[j])*2,f[1-o,plus]+3,c[1-o,plus]);
push(o,status+(four[j-1]+four[j])*3,f[1-o,plus]+3,c[1-o,plus]);
end
else
if x=0 then
begin
push(o,status+four[j]*y,f[1-o,plus]+1,c[1-o,plus]);
push(o,status+four[j-1]*y,f[1-o,plus]+2,c[1-o,plus]);
end
else
if y=0 then
begin
push(o,status+four[j-1]*x,f[1-o,plus]+1,c[1-o,plus]);
push(o,status+four[j]*x,f[1-o,plus]+2,c[1-o,plus]);
end
else
begin
push(o,status+four[j-1]*x+four[j]*y,f[1-o,plus]+2,c[1-o,plus]);
if x=y then push(o,status,f[1-o,plus]+1,c[1-o,plus]);
end
else
if map[i,j*2-2]=0 then
if (x=0)and(y=0) then
begin
push(o,status+four[j-1]*map[i,j*2-1],f[1-o,plus]+2,c[1-o,plus]);
push(o,status+four[j]*map[i,j*2-1],f[1-o,plus]+1,c[1-o,plus]);
end
else
if x=0 then
if y<>map[i,j*2-1] then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if y=0 then
begin
push(o,status+four[j-1]*x+four[j]*map[i,j*2-1],f[1-o,plus]+2,c[1-o,plus]);
if x=map[i,j*2-1] then push(o,status,f[1-o,plus]+1,c[1-o,plus]);
end
else
if y<>map[i,j*2-1] then continue
else push(o,status+four[j-1]*x,f[1-o,plus]+1,c[1-o,plus])
else
if map[i,j*2-1]=0 then
if (x=0)and(y=0) then
begin
push(o,status+four[j]*map[i,j*2-2],f[1-o,plus]+2,c[1-o,plus]);
push(o,status+four[j-1]*map[i,j*2-2],f[1-o,plus]+1,c[1-o,plus]);
end
else
if x=0 then
begin
push(o,status+four[j-1]*map[i,j*2-2]+four[j]*y,f[1-o,plus]+2,c[1-o,plus]);
if y=map[i,j*2-2] then push(o,status,f[1-o,plus]+1,c[1-o,plus]);
end
else
if y=0 then
if x<>map[i,j*2-2] then continue
else push(o,status,f[1-o,plus],c[1-o,plus])
else
if x<>map[i,j*2-2] then continue
else push(o,status+four[j]*y,f[1-o,plus]+1,c[1-o,plus])
else
if (x=0)and(y=0) then
begin
push(o,status+four[j-1]*map[i,j*2-2]+four[j]*map[i,j*2-1],f[1-o,plus]+2,c[1-o,plus]);
if map[i,j*2-1]=map[i,j*2-2] then push(o,status,f[1-o,plus]+1,c[1-o,plus]);
end
else
if x=0 then
if y<>map[i,j*2-1] then continue
else push(o,status+four[j-1]*map[i,j*2-2],f[1-o,plus]+1,c[1-o,plus])
else
if y=0 then
if x<>map[i,j*2-2] then continue
else push(o,status+four[j]*map[i,j*2-1],f[1-o,plus]+1,c[1-o,plus])
else
if (x<>map[i,j*2-2])or(y<>map[i,j*2-1]) then continue
else push(o,status,f[1-o,plus],c[1-o,plus]);
end;
end;
k:=hash(o,0);
if c[o,k]=0 then writeln(-1,' ',-1)
else writeln(f[o,k],' ',c[o,k]);
end;
close(input);
close(output);
end.