bzoj1193: [HNOI2006]马步距离

1193: [HNOI2006]马步距离

Time Limit: 10 Sec  Memory Limit: 162 MB

Description

在国际象棋和中国象棋中,马的移动规则相同,都是走“日”字,我们将这种移动方式称为马步移动。如图所示,
从标号为 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]);
}
原文地址:https://www.cnblogs.com/WQHui/p/8421840.html