bzoj2144 跳跳棋 二分+lca

来源:互联网 发布:淘宝客文案 编辑:程序博客网 时间:2024/05/02 00:12

这道题刚开始看以为是DP,,,我真是智障了。该DP的看成搜索,该二分的看成DP。。这状态有点危险。。
题意:现在有三个人a,b,c,每一个人可以跳过他左/右边的人,比如说一个人在x,一个在y,那么x可以跳到y+(y-x)(y>x),左边同理。。但是两个人之间不能有另一个人。
现在有三个目标位置和起始位置,让你计算最少的步数让三个人到达目标位置,并不要求人的顺序(即无论哪一个人都可以去任意的终点)。

题解:想法有点神。。果然脑洞还是不够大。
对于每一个状态(x,y,z):
中间的向外面跳->(2x-y,x,z) 或者(x,z,2z-y);
两边往中间跳:当y-x≠z-y时合法,不妨设y-x

type node=record    x,y,z:longint;end;const inf=2147483647;var    i,j,len,k,len1,len2:longint;    l,r,mid:longint;    a,b,c,d,a1:node;function min(x,y:longint):longint;begin    if x<y then exit(x) else exit(y);end;function pd(x,y:node):boolean;begin    if (x.x=y.x)and(x.y=y.y)and(x.z=y.z) then exit(true)    else exit(false);end;function lca(t:node;x:longint):node;var    i,j,u,v:longint;begin    len:=0;    while x<>0 do    begin        u:=t.y-t.x;        v:=t.z-t.y;        if (u=v)then exit(t);        if (u<v)then        begin            k:=min((v-1)div u,x);            t.x:=t.x+k*u;            t.y:=t.y+k*u;            x:=x-k;        end        else        begin            k:=min((u-1)div v,x);            t.y:=t.y-k*v;            t.z:=t.z-k*v;            x:=x-k;        end;        len:=len+k;    end;    exit(t);end;procedure swap(var x,y:longint);var    t:longint;begin    t:=x;    x:=y;    y:=t;end;begin    read(a.x,a.y,a.z);    if (a.y<a.x)then swap(a.x,a.y);    if (a.z<a.x)then swap(a.x,a.z);    if (a.z<a.y)then swap(a.y,a.z);     read(b.x,b.y,b.z);    if (b.y<b.x)then swap(b.x,b.y);    if (b.z<b.x)then swap(b.x,b.z);    if (b.z<b.y)then swap(b.y,b.z);    c:=lca(a,inf);    len1:=len;    d:=lca(b,inf);    len2:=len;      if (not pd(c,d))then    begin        writeln('NO');        exit;    end;    if (len1<len2)then    begin        a1:=a;        a:=b;        b:=a1;        swap(len1,len2);    end;    a:=lca(a,len1-len2);    l:=0;    r:=len2;    while (l<r)do    begin        mid:=(l+r)>>1;          if (pd(lca(a,mid),lca(b,mid)))then        r:=mid        else l:=mid+1;      end;      writeln('YES');    writeln((l<<1)+len1-len2);end. 
0 0
原创粉丝点击