BZOJ1193: [HNOI2006]马步距离

【传送门:BZOJ1193


简要题意:

  有一个无限大的图,给出起点坐标和终点坐标,要求以"日"字形移动,求出从起点到终点需要移动的次数


题解:

  找规律是第一想法。。

  结果手打了10*10的表,找不出来就放弃了

  然后转手向着化简时间复杂度的方向,因为直接BFS肯定会超,所以我们可以先移动到终点附近,然后再宽搜

  我们怎么移动。。

  贪心!!我们定义当移动到与终点同在一个10*10的矩阵时开始BFS,移动的时候,每次移动两次,因为有时候,连续跳两次之后,相当于只往上下左右直线走了4格,然后我们把起点坐标的纵坐标和横坐标与终点的相减并且取绝对值,这样子求起点到终点,就可以转化为从(0,0)到(x,y)(x,y就是起点纵坐标和横坐标与终点的相减的绝对值),然后就把时间复杂度大大减小了


参考代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int dx[9]={0,1,2,1,2,-1,-2,-1,-2};
int dy[9]={0,2,1,-2,-1,2,1,-2,-1};
struct node
{
    int x,y,d;
    node()
    {
        d=0;
    }
}list[1100];
bool v[21][21];
int main()
{
    int sx,sy,ex,ey;
    scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
    int x=abs(sx-ex),y=abs(sy-ey);
    int ans=0;
    while(x>10||y>10)
    {
        if(x<y) swap(x,y);
        if(x-4>y*2) x-=4;
        else x-=4,y-=2;
        ans+=2;
    }
    int head,tail;
    list[1].x=x;list[1].y=y;
    head=tail=1;
    memset(v,false,sizeof(v));
    v[x][y]=true;
    while(head<=tail)
    {
        node tno=list[head];
        for(int i=1;i<=8;i++)
        {
            int tx=tno.x+dx[i],ty=tno.y+dy[i];
            if(tx>20||ty>20) continue;
            if(tx==0&&ty==0)
            {
                ans+=tno.d+1;
                printf("%d\n",ans);
                return 0;
            }
            if(v[tx][ty]==false)
            {
                v[tx][ty]=true;
                list[++tail].x=tx;
                list[tail].y=ty;
                list[tail].d=tno.d+1;
            }
        }
        head++;
    }
    return 0;
}

 

posted @ 2018-01-31 15:02  Star_Feel  阅读(173)  评论(0编辑  收藏  举报