洛谷 P1852 國家集訓隊 跳跳棋

2022-06-03 08:48:11 字數 1539 閱讀 4852

跳跳棋是在一條數軸上進行的。棋子只能擺在整點上。每個點不能擺超過乙個棋子。

我們用跳跳棋來做乙個簡單的遊戲:棋盤上有3顆棋子,分別在a,b,c這三個位置。我們要通過最少的跳動把他們的位置移動成x,y,z。(棋子是沒有區別的)

跳動的規則很簡單,任意選一顆棋子,對一顆中軸棋子跳動。跳動後兩顆棋子距離不變。一次只允許跳過1顆棋子。

寫乙個程式,首先判斷是否可以完成任務。如果可以,輸出最少需要的跳動次數。

輸入格式:

第一行包含三個整數,表示當前棋子的位置a b c。(互不相同)

第二行包含三個整數,表示目標位置x y z。(互不相同)

輸出格式:

如果無解,輸出一行no。

如果可以到達,第一行輸出yes,第二行輸出最少步數。

輸入樣例#1: 

1 2 3

0 3 5

輸出樣例#1: 

yes

2

20% 輸入整數的絕對值均不超過10

40% 輸入整數的絕對值均不超過10000

100% 絕對值不超過10^9

非常有趣的一道題目。

可以發現只有唯一的一種方案向裡跳,並且一直這樣跳最後總會達到一種再也不能向裡跳的狀態。

於是我們就可以把向裡跳看成在樹上向父親走,而最後b-a = c-b 的狀態就是根節點。

首先如果兩個狀態的樹根不一樣,無解;否則就是乙個求lca的問題了,直接倍增即可。

/*

向前跳: a[1] -= a[2] (須滿足 a[1] > a[2])

向後跳: a[2] -= a[1] , a[0] += a[1] (須滿足 a[1] < a[2])

a[1] == a[2] 就不能跳了

*/#include#define ll long long

using namespace std;

struct node

}a,b;

int a[3],b[3];

unsigned int ans;

node getroot(node x));

else

}int getdeep(node x)

else

}node getnode(node x,int lef);

x.y-=o*x.z;

return getnode(x,lef-o); }

else;

x.x+=o*x.y,x.z-=o*x.y;

return getnode(x,lef-o);

} }inline void solve()

ans+=2;

}int main(),b=(node);

if(getroot(a)!=getroot(b))

solve();

puts("yes");

printf("%u\n",ans);

return 0;

}

P1852 國家集訓隊 跳跳棋

原 奇怪的字串 請前往 p2543 跳跳棋是在一條數軸上進行的。棋子只能擺在整點上。每個點不能擺超過乙個棋子。我們用跳跳棋來做乙個簡單的遊戲 棋盤上有3顆棋子,分別在a,b,c這三個位置。我們要通過最少的跳動把他們的位置移動成x,y,z。棋子是沒有區別的 跳動的規則很簡單,任意選一顆棋子,對一顆中軸...

洛谷P1852 跳跳棋

將三顆棋子看作三元組 x,y,z x,得其能轉移到的狀態有 large begin 2x y,x,z x,z,2z y x,2y z,y y x z y y,2y x,z y x 後兩個轉移只會滿足其中乙個,那麼將中間棋子向兩邊跳看作左右兒子,兩邊棋子向中間跳看作父親,根節點為滿足 y x z y ...

luogu P1852 國家集訓隊 跳跳棋

luogu 直接操作是不可能的,考慮發現一些性質.可以發現如果每次跳的棋子都是兩邊的,那麼最多只有一種方案,那麼就把這樣操作得到的狀態記為當前狀態的父親,從乙個狀態這樣做一定會結束.那麼如果兩個狀態只操作兩邊到達的最終狀態相同,那麼就可以互相轉換 步數的話,如果把這個看成一棵樹,那麼就是乙個樹上距離...