bzoj2144: 跳跳棋
昨天考试的神仙题
对于一个状态(x,y,z),有三种转移方案,往外跳两种,往里跳只有1种(考试的时候没有意识到)
那么可以看作一棵树,往外跳是子节点,往里跳是父亲
问题转换成树上两个点求最短路,这样就只用往里面跳了
考虑往里面跳是相当于一个辗转相除的,复杂度是logK,根据求LCA倍增的思想,不停往上跳就好。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; bool check(int ax,int ay,int az,int bx,int by,int bz) { int t1,t2,w; t1=ay-ax,t2=az-ay,w=0; if(t1>t2){swap(t1,t2);w^=1;} while((t2-1)/t1>0) { int c=(t2-1)/t1; if(w==0){ax+=c*t1;ay+=c*t1;} else {ay-=c*t1,az-=c*t1;} t2=t2-t1*c; swap(t1,t2);w^=1; } t1=by-bx,t2=bz-by,w=0; if(t1>t2){swap(t1,t2);w^=1;} while((t2-1)/t1>0) { int c=(t2-1)/t1; if(w==0){bx+=c*t1;by+=c*t1;} else {by-=c*t1;bz-=c*t1;} t2=t2-t1*c; swap(t1,t2);w^=1; } return ax==bx&&ay==by&&az==bz; } int getdep(int x,int y,int z) { int t1=y-x,t2=z-y,ret=0; if(t1>t2)swap(t1,t2); while((t2-1)/t1>0) { int c=(t2-1)/t1; ret+=c; t2=t2-t1*c; swap(t1,t2); } return ret; } void jumpK(int &x,int &y,int &z,int d) { int t1=y-x,t2=z-y,w=0; if(t1>t2){swap(t1,t2);w^=1;} while(d>0) { int c=min(d,(t2-1)/t1); d-=c; if(w==0){x+=c*t1;y+=c*t1;} else {y-=c*t1,z-=c*t1;} t2=t2-t1*c; swap(t1,t2);w^=1; } } int main() { freopen("2.in","r",stdin); freopen("2.out","w",stdout); int ax,ay,az,bx,by,bz; scanf("%d%d%d%d%d%d",&ax,&ay,&az,&bx,&by,&bz); if(ax>ay)swap(ax,ay); if(bx>by)swap(bx,by); if(ax<az&&az<ay)swap(ay,az); if(bx<bz&&bz<by)swap(by,bz); if(az<ax)swap(ay,az),swap(ax,ay); if(bz<bx)swap(by,bz),swap(bx,by); if(!check(ax,ay,az,bx,by,bz)){printf("NO\n");return 0;} else printf("YES\n"); //-------------------------------------- int da=getdep(ax,ay,az),db=getdep(bx,by,bz); int ans=0; if(da!=db) { if(da<db)swap(da,db),swap(ax,bx),swap(ay,by),swap(az,bz); ans+=da-db; jumpK(ax,ay,az,da-db); } if(ax==bx&&ay==by&&az==bz){printf("%d\n",ans);return 0;} for(int i=30;i>=0;i--) if(db>(1<<i)) { int tax=ax,tay=ay,taz=az; int tbx=bx,tby=by,tbz=bz; jumpK(ax,ay,az,(1<<i)); jumpK(bx,by,bz,(1<<i)); if(ax==bx&&ay==by&&az==bz) { ax=tax,ay=tay,az=taz; bx=tbx,by=tby,bz=tbz; } else ans+=(1<<i)*2,db-=(1<<i); } printf("%d\n",ans+2); return 0; }
pain and happy in the cruel world.