洛谷端題目連接node
loj端題目連接ios
題目大意:ide
在一條數軸上進行跳跳棋遊戲。棋子只能擺在整點上。每一個點不能擺超過一個棋子。用跳跳棋完成:棋盤上有3顆棋子,分別在a,b,c這三個位置。咱們要經過最少的跳動把他們的位置移動成x,y,z。spa
跳動的規則:任意選一顆棋子,對一顆中軸棋子跳動。跳動後兩顆棋子距離不變。一次只容許跳過1顆棋子。若是能夠完成輸出YES以及所需步數,若是不行輸出NO便可。code
對,只容許跳過一顆棋子(由於這個想了很久自閉了)blog
看完題目以後第一反應是否是:woc這什麼,跟LCA有什麼關係??這哪來的樹??遊戲
那就對了(%dalao)get
分類討論,發現對於每一種合法的狀態(也就是沒有棋子重合)只有三種狀況能走it
1.中點(y)向左邊跳io
2.中點(y)向右邊跳
3.左邊(或者右邊)往中間跳 =>能夠證實因爲只能跳過一顆棋子,在d1!=d2時只能走一個
這好像有點像二叉樹?(將1.2看作子節點,3看作父親節點)
對於1.2狀況,咱們能夠發現(如下以1爲例):
能夠知道,d1>d2時左邊的棋子不能跳了,咱們最多走d2/d1步,此時d2小於d1了換個方向走,當d2%d1等於0時走d2/d1-1步就到根了。
因此根據這個,咱們能夠求出開始狀態與結束狀態的祖先,判斷他們的祖先是否相等 =>由於祖先相同就能夠經過相反操做獲得
這個操做模擬一下就行了,咱們能夠用除來加快跳((一個個跳會超時的)
模擬部分:
1 int d1=y-x; 2 int d2=z-y; 3 if(d1<d2) 4 { 5 int step=d2/d1; 6 if(d2%d1==0) step--; 7 if(step>dis) step=dis; 8 x+=step*d1; 9 y+=step*d1; 10 if(x>y) swap(x,y); 11 dis-=step; 12 } 13 else 14 { 15 int step=d1/d2; 16 if(d1%d2==0) step--; 17 if(step>dis) step=dis; 18 z-=d2*step; 19 y-=d2*step; 20 if(z<y) swap(z,y); 21 dis-=step; 22 }
找到了公共祖先以後就能夠二分查找(查找往上跳的步數)
l是0,r是min(結果與公共祖先的距離,起點與公共祖先的距離)
1 int l=0,r=min(dep1,dep2),step=0; 2 while(l<=r) 3 { 4 int mid=l+r>>1; 5 b1=go(st,mid); 6 b2=go(ed,mid); 7 if(pd(b1,b2)) step=mid,r=mid-1; 8 else l=mid+1; 9 }
以上是我認爲的核心內容(看不懂就感性理解一下)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 struct node{ 5 int x,y,z; 6 }st,ed,b1,b2; 7 int dep1,dep2; 8 inline int read(){ 9 char ch; 10 int sign=1; 11 while((ch=getchar())<'0'||ch>'9') 12 if(ch=='-') sign=-1; 13 int res=ch-'0'; 14 while((ch=getchar())>='0'&&ch<='9') 15 res=res*10+ch-'0'; 16 return res*sign; 17 } 18 inline void sort(node &x){ 19 if(x.x>x.y) swap(x.x,x.y); 20 if(x.x>x.z) swap(x.x,x.z); 21 if(x.y>x.z) swap(x.y,x.z); 22 } 23 inline int findfather(node &b){ 24 int res=0; 25 sort(b); 26 while(b.x+b.z!=b.y*2) 27 { 28 int d1=b.y-b.x; 29 int d2=b.z-b.y; 30 if(d1<d2) 31 { 32 int step=d2/d1; 33 if(d2%d1==0) step--; 34 b.x+=step*d1; 35 b.y+=step*d1; 36 if(b.x>b.y) swap(b.x,b.y); 37 res+=step; 38 } 39 else 40 { 41 int step=d1/d2; 42 if(d1%d2==0) step--; 43 b.z-=step*d2; 44 b.y-=step*d2; 45 if(b.y>b.z) swap(b.y,b.z); 46 res+=step; 47 } 48 } 49 return res; 50 } 51 inline bool pd(node x,node y){ 52 if(x.x==y.x&&x.y==y.y&&x.z==y.z) return true; 53 return false; 54 } 55 inline int abs(int x){ 56 return x>=0?x:-x; 57 } 58 inline node go(node b,int dis){ 59 sort(b); 60 while(dis) 61 { 62 int d1=b.y-b.x; 63 int d2=b.z-b.y; 64 if(d1<d2) 65 { 66 int step=d2/d1; 67 if(d2%d1==0) step--; 68 if(step>dis) step=dis; 69 b.x+=step*d1; 70 b.y+=step*d1; 71 if(b.x>b.y) swap(b.x,b.y); 72 dis-=step; 73 } 74 else 75 { 76 int step=d1/d2; 77 if(d1%d2==0) step--; 78 if(step>dis) step=dis; 79 b.z-=d2*step; 80 b.y-=d2*step; 81 if(b.z<b.y) swap(b.z,b.y); 82 dis-=step; 83 } 84 } 85 return b; 86 } 87 int main(){ 88 st.x=read();st.y=read();st.z=read(); 89 ed.x=read();ed.y=read();ed.z=read(); 90 sort(st);sort(ed); 91 b1=st;b2=ed; 92 dep1=findfather(b1); 93 dep2=findfather(b2); 94 if(!pd(b1,b2)) 95 { 96 printf("NO\n"); 97 return 0; 98 } 99 else 100 { 101 int c=abs(dep1-dep2); 102 if(dep1<dep2) 103 ed=go(ed,c); 104 else if(dep1>dep2) 105 st=go(st,c); 106 int l=0,r=min(dep1,dep2),step=0; 107 while(l<=r) 108 { 109 int mid=l+r>>1; 110 b1=go(st,mid); 111 b2=go(ed,mid); 112 if(pd(b1,b2)) step=mid,r=mid-1; 113 else l=mid+1; 114 } 115 printf("YES\n"); 116 printf("%d",step*2+c); 117 } 118 return 0; 119 }