中国象棋中的跳马问题
时间限制: 5 Sec
内存限制: 128 MB
题目描述
现在棋盘的大小不一定,由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 <bits/stdc++.h>
using namespace std;
struct Position
{
int x;
int y;
};
struct node
{
int x;
int y;
int step;
};
int p, q ;
int block[101][101] = {0}; //记录障碍的坐标
int visited[101][101] = {0}; //标志是否已经访问
Position move_delta[8] = {{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}}; //马可以落脚的位置
Position bar[8] = {{-1,0},{-1,0},{0,1},{0,1},{1,0},{1,0},{0,-1},{0,-1}}; //绊马脚的位置
int in_chessboard(int x, int y)
{
if( x > 0 && x <= p && y > 0 && y <= q)
return true;
return false;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int step = 0, flag = 0; //记录走的步数
queue<node>que;
memset( block, 0, sizeof(block) );
memset( visited, 0, sizeof(block) );
int Start_X, Start_Y, End_X, End_Y ;
int i, n ;
cin >> p >> q ;
cin >> Start_X >> Start_Y >> End_X >> End_Y ;
cin >> n ;
for(i = 0 ; i < n ; ++i)
{
int x, y ;
cin >> x >> y ;
block[x][y] = 1 ;
visited[x][y] = true;
}
node P = {Start_X, Start_Y, step}, Q;
que.push(P);
visited[Start_X][Start_Y] = true;
while( !que.empty() )
{P = que.front();
int x = P.x;
int y = P.y;
que.pop();
if(x == End_X && y == End_Y) //到达终点后退出
{
flag = 1;
step = P.step;
break;
}
for( i = 0 ; i < 8; ++i )
{
int new_x = x+move_delta[i].x;
int new_y = y+move_delta[i].y;
if( (in_chessboard( new_x, new_y)) && ( !block[new_x][new_y] ) && (!block[x+bar[i].x][y+bar[i].y]) && (!visited[new_x][new_y]) )
{
//1.判断即将落脚的地方是否在棋盘内
//2.判断是否有障碍(能否落脚)
//3.判断是否绊马脚
//4.判断即将落脚的地方是否已经被访问过
Q = {new_x,new_y,P.step+1};
que.push(Q);
visited[new_x][new_y] = true; //如果成功则更新信息
}
}
}
if(flag == 1)
cout << step << endl ;
if(!flag)
cout << "can not reach!" << endl;
}
return 0;
}