bzoj1193: [HNOI2006]马步距离
1193: [HNOI2006]马步距离
Time Limit: 10 Sec Memory Limit: 162 MBDescription
在国际象棋和中国象棋中,马的移动规则相同,都是走“日”字,我们将这种移动方式称为马步移动。如图所示,
从标号为 0 的点出发,可以经过一步马步移动达到标号为 1 的点,经过两步马步移动达到标号为 2 的点。任给
平面上的两点 p 和 s ,它们的坐标分别为 (xp,yp) 和 (xs,ys) ,其中,xp,yp,xs,ys 均为整数。从 (xp,yp)
出发经过一步马步移动可以达到 (xp+1,yp+2)、(xp+2,yp+1)、(xp+1,yp-2)、(xp+2,yp-1)、(xp-1,yp+2)、(xp-2,
yp+1)、(xp-1,yp-2)、(xp-2,yp-1)。假设棋盘充分大,并且坐标可以为负数。现在请你求出从点 p 到点 s 至少
需要经过多少次马步移动?
Input
只包含4个整数,它们彼此用空格隔开,分别为xp,yp,xs,ys。并且它们的都小于10000000。
Output
含一个整数,表示从点p到点s至少需要经过的马步移动次数。
Sample Input
1 2 7 9
Sample Output
5
HINT
Source
Tip:
先暴力跑前面的;
再BFS;
Code:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> using namespace std; const int N=50,M=50; int dir[9][3]; int xp,yp,xs,ys,dis[108][108],flag[108][108],xx,yy,q[1000008][2],head,tail,ans; void bfs(){ while(head<tail){ head++; int x=q[head][1],y=q[head][2]; for(int i=1;i<=8;i++){ int x1=x+dir[i][1],y1=y+dir[i][2]; if(x1>100||x1<0) continue; if(y1>100||y1<0) continue; if(flag[x1][y1]) continue; dis[x1][y1]=dis[x][y]+1; flag[x1][y1]=1; tail++; q[tail][1]=x1; q[tail][2]=y1; if(x1==50&&y1==50) return; } } } int main(){ scanf("%d%d%d%d",&xp,&yp,&xs,&ys); dir[1][1]=-2; dir[1][2]=1; dir[2][1]=-1; dir[2][2]=2; dir[3][1]=1; dir[3][2]=2; dir[4][1]=2; dir[4][2]=1; dir[5][1]=2; dir[5][2]=-1; dir[6][1]=1; dir[6][2]=-2; dir[7][1]=-1; dir[7][2]=-2; dir[8][1]=-2; dir[8][2]=-1; xx=abs(xp-xs); yy=abs(yp-ys); while(xx+yy>=50){ if(xx<yy) swap(xx,yy); if(xx-4>=yy*2) xx-=4; else xx-=4,yy-=2; ans+=2; } xx+=50; yy+=50; head=0; tail=1; q[1][1]=xx; q[1][2]=yy; dis[xx][yy]=0; flag[xx][yy]=1; bfs(); printf("%d",ans+dis[50][50]); }