假设下图是中国传统的象棋棋盘的一部分:
在象棋中,“馬”走“日”的规则,如上图,一同是以上8个方向,红色的旗子是“馬”要攻击的对象,请找出攻击的最短路径的步数
下面2个箭头所指的路径都是到达红色目标的路径(当然也许并不是最短路径)
要求输入:
M, N //M代表一共有多少行,N代表一共有多少列
StartX SrartY EndX EndY
例如:
9 9 //表示是一个9*9的矩阵
3 5 2 8 //分别表示起点的横坐标,纵坐标和终点的横坐标纵坐标
要求输出达到攻击点的最短步数:
2
分析:
本题采用广度搜索的方法去遍历,一层一层向外扩散,一旦到达了红色目标的坐标,则广度搜索结束。
首先根据象棋里“馬走日”的规则,一共有八个方向。所有用个2维数组去记录这8个方向。
direction[8][2]={{1,-2},{2,-1},{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2}};
再用一个二维数组记录遍历到的点,这个点包括X坐标,Y坐标以及步数。
即这个数组的基本形式是visit[][3];第二维分别记录X坐标,Y坐标以及步数。
分别用head和tail游标指向visit数组的头节点和尾节点,head坐标表示的其实是某一个父节点。把从该父节点出发,满足条件的点,全部加入到队列中,等到全部加完以后,移动head节点,指向下一个节点,找下个父节点,如此往复循环,知道head等于tail的时候。
详细代码:
#include <iostream>
using namespace std;
//预设一个100*100的棋盘
int Array[100][100];
int Answer;
int M, N;
int EndX, EndY;
int direction[8][2] = { { 1,-2 },{ 2,-1 },{ 2,1 },{ 1,2 },{ -1,2 },{ -2,1 },{ -2,-1 },{ -1,-2 } };
//游标分别指向visit数组的头部和尾部
int head, tail;
int visit[10000][3];
void BFS()
{
++tail;
//在visit数组中还有没有遍历完的点
while (tail > head)
{
//取出父节点当前的X坐标值和Y坐标值
int currentX = visit[head][0];
int currentY = visit[head][1];
//分别遍历8个方向
int i;
for (i = 0; i < 8; ++i)
{
//在父节点的基础上,分别走过8个方向以后得到的目的地坐标值
int targetX = currentX + direction[i][0];
int targetY = currentY + direction[i][1];
cout << "targetX : is " << targetX << " targetY : is " << targetY << endl;
//如果目的地坐标值已经超过M*N的范畴,则取下一个方向比较
if (targetX < 0 || targetX > M || targetY < 0 || targetY > N)
{
continue;
}
//如果目的地的坐标值就是最终的坐标值,则就是所求的步长,即在父节点的步长上再加上1
if (targetX == EndX && targetY == EndY)
{
Answer = visit[head][2] + 1;
return;
}
//如果目的地还没有走过,则可以走,并且把目的地的坐标即步长放入队列的尾部
if ( 0 == Array[targetX][targetY])
{
Array[targetX][targetY] = 1;
visit[tail][0] = targetX;
visit[tail][1] = targetY;
//步长仅仅是在父节点的基础上+1
visit[tail][2] = visit[head][2]+1;
++tail;
}
}
//父节点的游标加1,形成一个新的父节点
head++;
}
}
int main()
{
int StartX, StartY;
cin >> M >> N;
cin >> StartX >> StartY >> EndX >> EndY;
int i, j;
//初始化棋盘上的所有节点,都设置为0,表示未曾走过
for (i = 0; i < M; ++i)
{
for (j = 0; j < N; ++j)
{
Array[i][j] = 0;
}
}
Answer = 0;
//在广度搜索之前再初始化头节点和尾节点
head = 0;
tail = 0;
//把起始坐标的X值和Y值已经步长赋值给visit数组
visit[0][0] = StartX;
visit[0][1] = StartY;
visit[0][2] = 0;
//父节点标记为是已经走过的点,0表示未访问过,1表示已经访问过了
Array[StartX][StartY] = 1;
//广度搜索开始
BFS();
cout << "Minimum step number is : " << Answer << endl;
return 0;
}