bzoj1193 马步距离

Description

求点(xs,ys)走马步到(xp,yp)的最小步数

 

Input

只包含4个整数,它们彼此用空格隔开,分别为xp,yp,xs,ys。并且它们的都小于10000000。

Output

含一个整数,表示从点p到点s至少需要经过的马步移动次数。

设起点与终点的坐标差为(x,y)

则问题转化为求向量方程a*(1,2)+b*(2,1)+c*(1,-2)+d*(2,-1)==(x,y)的解满足a,b,c,d为整数且绝对值之和最小。

由对称性可令0≤y≤x

使a*(1,2)+b*(2,1)接近(x,y)并求c,d

使b*(2,1)+d*(2,-1)接近(x,y)并求a,c

枚举即可

#include<cstdio>
inline void mins(int&a,int b){if(a>b)a=b;}
inline void abss(int&a){if(a<0)a=-a;}
inline int abs(int a){return a>0?a:-a;}
int main(){
    int x,y,x2,y2,as,bs,cs,ds,ans=0x7fffffff;
    scanf("%d%d%d%d",&x,&y,&x2,&y2);
    x-=x2;y-=y2;
    abss(x);abss(y);
    if(x<y){int c=x;x=y;y=c;}
    int as0=(y*2-x)/3,bs0=(x*2-y)/3;
    for(as=as0-10;as<=as0+10;as++)
    for(bs=bs0-10;bs<=bs0+10;bs++){
        int v1=x-as-bs*2,v2=2*as+bs-y;
        int v3=(v1+v2)/3;
        cs=v2-v3;ds=v1-v3;
        if(as+2*bs+cs+2*ds==x&&2*as+bs-2*cs-ds==y)mins(ans,abs(as)+abs(bs)+abs(cs)+abs(ds));
    }
    bs0=(x+y*2)/4;
    int ds0=(x-y*2)/4;
    for(bs=bs0-10;bs<=bs0+10;bs++)
    for(ds=ds0-10;ds<=ds0+10;ds++){
        int v1=x-bs*2-ds*2,v2=(y-bs+ds)/2;
        as=(v1+v2)/2;cs=(v1-v2)/2;
        if(as+2*bs+cs+2*ds==x&&2*as+bs-2*cs-ds==y)mins(ans,abs(as)+abs(bs)+abs(cs)+abs(ds));
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/ccz181078/p/5209526.html