JZOJ 4628 立方体【NOIP2016提高A组模拟7.15】

立方体

题目描述

这里写图片描述

样例输入

这里写图片描述

样例输出

这里写图片描述

样例输入

e2 e3 0 8 1 2 1 1

样例输出

5

数据范围

这里写图片描述

题解

假设题目给出的序列是数组 S ,例如,输入如果是样例数据,则S=(0,8,1,2,1,1)

这一题,明显就是一题搜索题。
我们可以设一个状态, F [i][ j ][k1][ k2 ][ k3 ][ k4 ][ k5 ][ k6 ]表示当前色子滚到了位置( i j),前后上下左右分别对应的数值是 S [k1]、 S [k2]、 S [k3]、 S [k4]、 S [k5]、 S [k6]。

这样当然是非常麻烦的,事实上,我们只需要确定色子两个相邻位置的状态就可以确定整个色子的状态了,于是我们可以设成 F [i][ j ][k1][ k2 ],表示色子滚到了位置( i j),后面和左面对应的数值分别为 S [k1]、 S [k2]。

当然,我们可以预处理出色子向前后左右滚动的转移矩阵。

同时,在跑SPFA时,我们同时维护一下色子的状态,转移时再通过转移矩阵将色子的状态转移一下即可。

然后,初始化为 F [xbegin][ ybegin ][2][6]= S5 。其中( xbegin ybegin )是开始位置。

最后, ans = Π6k1=1 Π6k2=1 max ( F [xend][ yend ][ k1 ][ k2 ]) 其中( xend yend )是结束位置。

Code(Pascal)

const
    cqy=8;
    jx=1001;
    mo=1000000;
var
    dl:array[0..1000000,1..8] of longint;
    bz:array[0..9,0..9,1..6,1..6] of boolean;
    zx:array[0..9,0..9,1..6,1..6] of int64;
    gd:array[0..9,0..9,1..6] of longint;
    ok:array[0..6] of longint;
    wz:array[1..4,1..2] of longint=((1,0),(0,1),(-1,0),(0,-1));
    zy:array[1..4,1..6] of longint=
    ((3,2,6,4,1,5),
    (1,3,4,5,2,6),
    (5,2,1,4,6,3),
    (1,5,2,3,4,6));//所谓的转移矩阵,我打的程序和上面讲的方法不太一样,但思想上是一样的
    ch:char;
    ans:int64;
    bx,by,ex,ey,i,j,k,l,o,p,x,y,nx,ny,nk,no:longint;
function min(a,b:longint):longint;
    begin
        if a<b then exit(a)
        else exit(b);
    end;
begin
    for i:=1 to cqy do
    for l:=1 to cqy do
    for j:=1 to 6 do
    gd[i,l,j]:=jx;
    read(ch);
    by:=ord(ch)-96;
    read(bx);
    read(ch);
    read(ch);
    ey:=ord(ch)-96;
    read(ex);
    read(ok[1],ok[6],ok[5],ok[4],ok[3],ok[2]);
    dl[1,1]:=1;
    dl[1,2]:=2;
    dl[1,3]:=3;
    dl[1,4]:=4;
    dl[1,5]:=5;
    dl[1,6]:=6;
    dl[1,7]:=bx;
    dl[1,8]:=by;
    for i:=1 to 8 do
    for l:=1 to 8 do
    for k:=1 to 6 do
    for j:=1 to 6 do
    zx[i,l,k,j]:=maxlongint;
    zx[bx,by,dl[1,1],dl[1,2]]:=ok[3];
    i:=0;
    j:=1;
    bz[bx,by,dl[1,1],dl[1,2]]:=true;
    while i<>j do
    begin
        inc(i);
        x:=dl[i,7];
        y:=dl[i,8];
        for l:=1 to 4 do
        if (x+wz[l,1]>0) and (x+wz[l,1]<=cqy)
        and (y+wz[l,2]>0) and (y+wz[l,2]<=cqy)
        and (zx[x,y,dl[i,1],dl[i,2]]+ok[dl[i,zy[l,3]]]<zx[x+wz[l,1],y+wz[l,2],dl[i,zy[l,1]],dl[i,zy[l,2]]]) then
        begin
            nx:=x+wz[l,1];
            ny:=y+wz[l,2];
            nk:=dl[i,zy[l,1]];
            no:=dl[i,zy[l,2]];
            zx[nx,ny,nk,no]:=zx[x,y,dl[i,1],dl[i,2]]+ok[dl[i,zy[l,3]]];
            if bz[nx,ny,nk,no]=false then
            begin
                bz[nx,ny,nk,no]:=true;
                inc(j);
                dl[j,7]:=nx;
                dl[j,8]:=ny;
                for k:=1 to 6 do
                dl[j,k]:=dl[i,zy[l,k]];
            end;
        end;
        bz[x,y,dl[i,1],dl[i,2]]:=false;
    end;
    ans:=maxlongint;
    for i:=1 to 6 do
    for j:=1 to 6 do
    ans:=min(ans,zx[ex,ey,i,j]);
    writeln(ans);
end.
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值