【传送门: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; }