bzoj1193 [HNOI2006]马步距离 构造+枚举

首先肯定不是直接按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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值