您的位置:首页 > 其它

BZOJ系列1193《[HNOI2006]马步距离》题解

2015-03-02 08:50 274 查看

Description



Input

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

Output

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

Sample Input

1 2 7 9

Sample Output

5

分析:好熟悉,去年NOIP前老师出的模拟赛用过,差不多。

当时的题是某个点到原点的,这道题是两个点之间的,差不多,没什么区别。。。

策略就是:搜索+贪心优化搜索范围。

两个点间的距离比较大,纯搜索不现实,所以需要找到一个规律。

这就需要贪心优化了,因为走得步子是有规律的,所以可以按这个规律将两个点的距离拉近。

本题将两个点拉到了100*100的方框内,足以搜索了。

下面说一下怎么贪心:

先将一个点置于原点,另一个点置于第一象限。

while(x+y>=50)
{
if(x<y) swap(x,y);
if(x-4>=2*y) x-=4;
else x-=4,y-=2;
ans+=2;
}
x+=50,y+=50;
x和y代表两点间的横纵距离。

然后广搜!!

我们知道马走的方式,就可以枚举出每个点该怎么走,直到走到终点(50,50),再加上贪心时走过的ans。

输出AC。

代码如下:

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int dx[8]={1,1,-1,-1,2,2,-2,-2};
const int dy[8]={2,-2,2,-2,1,-1,1,-1};
int XP,YP,XS,YS,x,y,ans=0;
int q[100010][3],head=0,tail=1;
int d[110][110];
void init()
{
scanf("%d%d%d%d",&XP,&YP,&XS,&YS);
x=abs(XP-XS),y=abs(YP-YS);
while(x+y>=50) { if(x<y) swap(x,y); if(x-4>=2*y) x-=4; else x-=4,y-=2; ans+=2; } x+=50,y+=50;
}
void BFS()
{
memset(d,-1,sizeof(d));
q[0][1]=x,q[0][2]=y,d[x][y]=0;
while(head!=tail)
{
int x=q[head][1],y=q[head++][2];
for(int i=0;i<8;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(nx<0||ny<0||nx>100||ny>100||d[nx][ny]!=-1) continue;
d[nx][ny]=d[x][y]+1;
q[tail][1]=nx,q[tail++][2]=ny;
if(nx==50&&ny==50) return;
}
}
}
void work()
{
BFS();
ans+=d[50][50];
printf("%d\n",ans);
}
int main()
{
init();
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: