zoukankan      html  css  js  c++  java
  • 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]);
    }
  • 相关阅读:
    最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现
    动态规划算法(后附常见动态规划为题及Java代码实现)
    2个字符串的最长公共子串
    VS2010常用快捷键
    错误代码errno值的含义
    几个常用I/O函数用法(printf,fprintf等)
    查看CPU位数的方法
    关于函数指针的总结
    日本标点符号的输入总结
    共享内存及信号量的几个函数介绍
  • 原文地址:https://www.cnblogs.com/WQHui/p/8421840.html
Copyright © 2011-2022 走看看