bzoj2144 跳跳棋 二分+lca

    xiaoxiao2026-01-11  4

    这道题刚开始看以为是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.
    转载请注明原文地址: https://ju.6miu.com/read-1305874.html
    最新回复(0)