不同的LCA——luoguP1852跳跳棋

洛谷端題目連接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         }        
View Code

找到了公共祖先以後就能夠二分查找(查找往上跳的步數) 

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         }      
View Code

以上是我認爲的核心內容(看不懂就感性理解一下)


 

  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 }
相關文章
相關標籤/搜索