扩展欧几里求最优解
https://zoj.pintia.cn/problem-sets/91827364500/problems/91827369176
题意:有一数轴 , 问从A点到B点最少需要几步。可以有6中方式行走,左右a , b a+b.
解法:设走了x步a , y步b。有方程 ax + by = B-A ,转化为求|x| + |y|的最小值,x , y 分别是两条直线。
|x|+|y|最小值在x=x+bt与y=y-at两条直线交点附近。
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define cin(a) scanf("%d",&a)
#define pii pair<int,int>
#define ll long long
#define gcd __gcd
#define mod 1000000007
#define INF 0x3f3f3f3f
const ll inf = 0x3f3f3f3f;
const int M = 1e9+7;
const int N = 100009 ;
ll x , y , d ;
void gcd(ll a , ll b , ll &d , ll &x , ll &y)
{
if(b == 0)
{
x = 1 ;
y = 0 ;
d = a ;
}
else{
gcd(b , a%b , d , x , y);
ll t = x ;
x = y ;
y = t - (a/b) * y ;
}
}
ll cal(ll a , ll b , ll c)
{
gcd(a , b , d , x , y);
if(c % d) return -1 ;
else{
return 1;
}
}
int main()
{
int t ;
scanf("%d" , &t);
while(t--)
{
ll A , B , a , b ;
scanf("%lld%lld%lld%lld" , &A,&B , &a, &b);
ll c = B - A ;
ll t = cal(a , b , c);
if(t == -1){
cout << -1 << endl ;
continue ;
}
else
{
x *= c / d ;
y *= c / d ;
a /= d ;
b /= d ;
ll ans = inf * inf , tmp ;//inf要用ll,在这wa了几发
ll mid = (y - x) / (a + b);//mid为两直线交点
for(ll T = mid - 1 ; T <= mid + 1 ; T++)
{
if((x + b*T)*(y - a*T) >= 0)//x ,y 同号
{
tmp = max(abs(x+b*T) , abs(y-a*T));//取最大那个就可以,相同部分取x+y每步
}
else{
tmp = abs(x - y + (a + b) * T);//都取
}
ans = min(tmp , ans);
}
cout << ans << endl ;
}
}
return 0;
}

浙公网安备 33010602011771号