1. 程式人生 > >ZOJ-3593 One Person Game(擴充套件歐幾里得)

ZOJ-3593 One Person Game(擴充套件歐幾里得)

題意

座標軸上,一個人想從 A 點走到 B 點,每次移動可以向左或向右走 a 個單位、 b 個單位或 a+b 個單位,求最少移動多少次。
231A,B<231
0<a,b<231

思路

先將原題轉化為向右移動 BA 個單位需要的最小步數。如果不考慮長度為 a+b 的移動,不難看出,不可能向左移動 a 長度後,又向右移動 a 長度。那麼可以設向右的 a 移動作了 k1 次(如果向左移動 k1 為負),向右的 b 移動作了 k2 次。所以這個移動的次數即為

|k1|+|k2|。用擴充套件歐幾里得求出 k1,k2 的特解後,寫出通解 k1=k1+bKk2=k2aK
k1k2 同號時,結果為 max(k1,k2) ,當 k1k2 異號時,結果為 |k1|+|k2| ,我們可以考慮使 |k1k2| 最小。
|k1k2|=|k1+bK+k2aK|=|k1k2+(ba)K|
故當原式為零時 K=k2k1a+b
但原式不一定正好為零,所以在 [K1,K+1] 這個範圍搜尋,找到最優解即可。

程式碼

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define Abs(x) ((x>0)?(x):-(x)) typedef long