火星移民(mars)

火星移民(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.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值