广度搜索的应用实例

假设下图是中国传统的象棋棋盘的一部分:

在象棋中,“馬”走“日”的规则,如上图,一同是以上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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值