移动 | ||||||
| ||||||
Description | ||||||
在平面坐标系内,有两个坐标轴x轴和y轴。(x,y)表示点的坐标。 有一点处于(x1,y1)位置上,他可以向相临8个位置移动(移动方式见下图)。 划定范围:此点只可以在[0<=x<=300,0<=y<=300]范围内移动。 要求:给出起始位置(x1,y1)和目标位置(x2,y2),要求同学求出从起始位置移动到目标位置所需的最少次数。 | ||||||
Input | ||||||
输入包括多组测试用例。 对于每组测试用例,包含4个正整数,x1,y1,x2,y2,范围均为[0,300]。 | ||||||
Output | ||||||
输出移动所需的最少次数。 | ||||||
Sample Input | ||||||
0 0 1 2 0 0 2 1 | ||||||
Sample Output | ||||||
1 1 | ||||||
Hint | ||||||
宽度优先搜索 | ||||||
Author | ||||||
卢俊达 |
解题思路:放眼望去,本题适用于广度优先搜索。广度优先搜索,最好用队列实现。由于它涉及到点的坐标问题,所以推荐使用结构体来描述这个点。我们用X[9],,Y[9]来表示它的八个方向,每遍历一遍,都等于其上一次遍历的步数加一。
题解:
#include<bits/stdc++.h>///该头文件为万能头文件,有些学校oj不能使用,读者可根据需要自行修改
using namespace std;
const int MAXN=305;
int vis[MAXN][MAXN];
int X[9]={0,1,1,2,2,-1,-1,-2,-2};
int Y[9]={0,2,-2,1,-1,2,-2,-1,1};
struct point
{
int x;
int y;
};
queue<point>q;
point xy(int x,int y)
{
point m;
m.x=x;
m.y=y;
return m;
}
int bfs(point a,point b)
{
vis[a.x][a.y]=1;
q.push(a);
while(!q.empty())
{
point head=q.front();
q.pop();
if(head.x==b.x&&head.y==b.y)
{
return vis[head.x][head.y];///若找到需要的点则结束循环并返回
}
else
{
for(int i=1;i<=8;i++)
{
point t;
t.x=head.x+X[i];
t.y=head.y+Y[i];
if(t.x>=0&&t.x<=300&&t.y>=0&&t.y<=300&&vis[t.x][t.y]==0)///把八个方向都放到队列中去
{
vis[t.x][t.y]=vis[head.x][head.y]+1;///每一步都等于其上一步+1
q.push(xy(t.x,t.y));
}
}
}
}
}
int main()
{
point a,b;
while(~scanf("%d %d %d %d",&a.x,&a.y,&b.x,&b.y))
{
memset(vis,0,sizeof(vis));
while(!q.empty())///清空队列
{
q.pop();
}
int ans=bfs(a,b);
printf("%d\n",ans-1);///ans-1是因为在上面的模块里把(0,0)点的步数记为了1.
}
return 0;
}