题目描述
现在棋盘的大小不一定,由p,q给出,并且在棋盘中将出现障碍物(限制马的行动,与象棋走法相同)
输入
第一行输入n表示有n组测试数据。
每组测试数据第一行输入2个整数p,q,表示棋盘的大小(1<=p,q<=100)。
每组测试数据第二行输入4个整数,表示马的起点位置与终点位置。(位置的取值范围同p,q)
第三行输入m表示图中有多少障碍。
接着跟着m行,表示障碍的坐标。
输出
马从起点走到终点所需的最小步数。
如果马走不到终点,则输入“can not reach!”
样例输入
2
9 10
1 1 2 3
0
9 10
1 1 2 3
8
1 2
2 2
3 3
3 4
1 4
3 2
2 4
1 3
样例输出
1
can not reach!
提示
此题是一个搜索题,可用DFS或BFS,建议选择BFS(广搜)。一开始把马的起始点加入队列,然后用广搜的思想把此点能到达的其他点加入队列,这里需要一个数组用来记录此点在之前是否已经加入队列,如果加入过队列当中,就不需要再加入了,直到队列里的元素为空,或者搜索到了终点,搜索即停止,然后输出相应答案即可。
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
int num[6];
bool visti[101][101];
struct postion2
{
int x;
int y;
int sum;
};
struct postion1
{
int x;
int y;
};
postion1 dir[8]= {{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1},{2,1},{1,2},{-1,2}};
//postion1 dir2[8]= {{-1,0},{-1,0},{0,-1},{0,-1},{1,0},{1,0},{0,1},{0,1}};
postion1 dir2[8]= {{-1,0},{0,-1},{1,0},{0,1}}; //象棋中马的走法有限制
queue<postion2> que;
int zhangai[101][101];
int ans=0,m;
int p,q; //棋盘大小
bool check(int a,int b)
{
if(a<=p && a>0 && b<=q && b>0)
return true;
return false;
}
int bfs()
{
postion2 be,da,he;
be.x=num[0];
be.y=num[1];
be.sum=0;
que.push(be);
visti[num[0]][num[1]]=true;
while(!que.empty())
{
da=que.front();
que.pop();
if(da.y==num[3] && da.x==num[2])
return da.sum;
for(int i=0; i<8; i++)
{
if(check(da.x+dir[i].x,da.y+dir[i].y) && !visti[da.x+dir[i].x][da.y+dir[i].y] && !zhangai[da.x+dir[i].x][da.y+dir[i].y] && zhangai[da.x+dir2[i/2].x][da.y+dir2[i/2].y]==0)
{
he.x=da.x+dir[i].x;
he.y=da.y+dir[i].y;
he.sum=da.sum+1;
que.push(he);
visti[da.x+dir[i].x][da.y+dir[i].y]=true;
}
}
}
return -1;
}
int main()
{
int n,i;
scanf("%d",&n); // n组数据
while(n--)
{
memset(zhangai,0,sizeof(zhangai));
memset(visti,false,sizeof(visti));
while(!que.empty()) que.pop();
int x,y;
scanf("%d %d",&p,&q);
scanf("%d %d %d %d",&num[0],&num[1],&num[2],&num[3]);
scanf("%d",&m);
for(i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
zhangai[x][y]=1;
visti[x][y]=true;
}
ans=bfs();
if (ans!=-1)
printf("%d\n",ans);
else
printf("can not reach!\n");
}
return 0;
}