首先肯定不是直接按xy跳,因为会有几个特殊位置:
(0,0)到(1,1)
(0,0)到(1,0)
(0,0)到(4,4)
正常逼近是那长距离跳2,短距离跳1,但在这几个类似的点上是不行的
首先,一定会有一段两个坐标都逼近的一部分,而且还很多
都逼近的话,一定是当前位置最优解,但只逼近的话,当前位置不一定能落在目标点上
通过手玩可以发现,这种情况,离目标点的距离已经非常近,在考虑接下来怎么走,实际上也可以考虑成从哪里出发,能正好通过逼近到达目标点,实际上这两个问题是等价的
所以就相当于把逼近之外比较巧妙的部分用枚举法处理完,直接逼近判断就可以了
码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
queue<int>qxx,qyy,ff;
int xx,yy,i,j,xxxx,yyyy,ans=199999999,lxx,lyy,lff;
bool b[404][404];
int check(int xx,int yy)
{
int lin=0;
if(xx<yy)swap(xx,yy);
if(xx>=yy*2)
{
lin+=yy;
xx-=2*yy;
yy=0;
if(xx%4==0)return lin+xx/2;
else return 199999999;
}else
{
int o=xx-yy;
lin+=o;//走到相同
yy-=o;xx-=2*o;
//一起走
if(xx%3==0)return xx/3*2+lin;
else return 199999999;
}
}
int main()
{
scanf("%d%d%d%d",&xx,&yy,&xxxx,&yyyy);
qxx.push(0);
qyy.push(0);
ff.push(0);
while(!ff.empty())
{
lxx=qxx.front();
lyy=qyy.front();
lff=ff.front();
qxx.pop(),qyy.pop(),ff.pop();
if(lxx<-100||lxx>100||lyy<-100||lyy>100)continue;
ans=min(lff+check(abs(lxx+xx-xxxx),abs(lyy+yy-yyyy)),ans);
if(!b[lxx+2+120][lyy+1+120])
{
b[lxx+2+120][lyy+1+120]=1;
ff.push(lff+1);
qxx.push(lxx+2);
qyy.push(lyy+1);
}
if(!b[lxx+2+120][lyy-1+120])
{b[lxx+2+120][lyy-1+120]=1;
ff.push(lff+1);
qxx.push(lxx+2);
qyy.push(lyy-1);
}
if(!b[lxx-2+120][lyy+1+120])
{
b[lxx-2+120][lyy+1+120]=1;
ff.push(lff+1);
qxx.push(lxx-2);
qyy.push(lyy+1);
}
if(!b[lxx-2+120][lyy-1+120])
{b[lxx-2+120][lyy-1+120]=1;
ff.push(lff+1);
qxx.push(lxx-2);
qyy.push(lyy-1);
}
if(!b[lxx+1+120][lyy+2+120])
{
b[lxx+1+120][lyy+2+120]=1;
ff.push(lff+1);
qxx.push(lxx+1);
qyy.push(lyy+2);
}
if(!b[lxx+1+120][lyy-2+120])
{b[lxx+1+120][lyy-2+120]=1;
ff.push(lff+1);
qxx.push(lxx+1);
qyy.push(lyy-2);
}
if(!b[lxx-1+120][lyy+2+120])
{
b[lxx-1+120][lyy+2+120]=1;
ff.push(lff+1);
qxx.push(lxx-1);
qyy.push(lyy+2);
}
if(!b[lxx-1+120][lyy-2+120])
{b[lxx-1+120][lyy-2+120]=1;
ff.push(lff+1);
qxx.push(lxx-1);
qyy.push(lyy-2);
}
}
printf("%d",ans);
}