One Person Game
There is an interesting and simple one person game. Suppose there is a number axis under your feet. You are at point A at first and your aim is point B. There are 6 kinds of operations you can perform in one step. That is to go left or right by a,band c, here c always equals to a+b.
You must arrive B as soon as possible. Please calculate the minimum number of steps.
Input
There are multiple test cases. The first line of input is an integer T(0 < T ≤ 1000) indicates the number of test cases. Then T test cases follow. Each test case is represented by a line containing four integers 4 integers A, B, a and b, separated by spaces. (-231 ≤ A, B < 231, 0 < a, b < 231)
Output
For each test case, output the minimum number of steps. If it's impossible to reach point B, output "-1" instead.
Sample Input
2
0 1 1 2
0 1 2 4
Sample Output
1
-1
————————————————
题目的大意是说有三种操做方式,每一次可以移动距离a或者移动距离b或者一次性移动a+b;由于有正反两种方向,所以相当于有6种操作。
起点和终点是等价的,从起点到终点和终点到起点是互逆的过程。所以我们用ax+by=abs(A-B)方程来求解,由于a+b是a和b的线性组合,所以一次性移动a+b的情况也被考虑进来(不妨假设它先移动a再移动一次b)。
通过分析我们不难发现只有两种情况:
1、x,y都是非负方向的,这时候我们知道,min(x,y)可以合并成a+b步。所以我们的答案就算max(x,y);
2、x和y是相反的。这种情况下一定是先以a(b)移动对应步数,然后返回时以b(a)移动对应步数,不存在有a+b的情况,假设有a+b出现在正向移动的过程中,那么折返时,必然也会出现a和b,这样必然会与前面的所有a+b的情况抵消,否则就得归为第一类情况.所以ans=abs(x)+abs(y);
讨论完上面情况:
1、当1时x+y取最小,有均值不等式得,x和y最接近时可能去最小。枚举x=y的前后两点和本身,一定包含极限情况
2、可以假设某种状态为abs(x)+abs(y)最小
如果黑色的线代表了最优解,那么蓝色的线不可能存在,只可能还有红色线表示的解。所以我们得到结论:出现最优解时,abs(x)最小,abs(y)最小。
所以上代码:
#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1;
y=0;
return a;
}
int t=exgcd(b,a%b,x,y);
int tx=x;
x=y;
y=tx-a/b*y;
return t;
}
int solve(int a,int b,int c){
int q=gcd(a,b);
if(c%q!=0){
return -1;
}
int x,y;
int ans=1e8;
a/=q,b/=q,c/=q;
q=exgcd(a,b,x,y);
x*=c;
y*=c;//现在知道对于每一种情况而言都是x与y趋近时取得最优解
int k=(y-x)/(a+b);//当x,y相等时的k(相对于求出来的初始x0,y0而言),由于是整数,所以不一定就是这个值,枚举它附近的点
for(int i=k-1;i<=k+1;i++){
if(abs(x+b*i)+abs(y-a*i)==abs(x+b*i+y-a*i))
ans=min(ans,max(x+b*i,y-a*i));
else
ans=min(ans,abs(x+b*i)+abs(y-a*i)); //这个由绝对值不等式得出
}
return ans;
}
int main(){
int t;
cin>>t;
while(t--){
int A,B,a,b,c;
cin>>A>>B>>a>>b;
c=abs(A-B);
int ans=solve(a,b,c);
cout<<ans<<endl;
}
return 0;
}
注:y=y0-a*k
x=x0+b*k
当x=y时
x0+b*k=y0-a*k;
k=(y0-x0)/(a+b);