广搜例题

给定一个n*m大小的迷宫,其中*代表不可通过的墙壁,而‘.代表平地,S表示起点,T表示终点。移动过程中,如果当前位置是(x,y)(下标从0开始),且每次只能前往上下左右四个位置的平地,求从起点S到达终点T的最少步数。

样例:

.....

.*.*.

.*S*.

.***.

...T*

在上面样例中,S的坐标为(2,2),T的坐标为(4,3)。

在本题中,由于求的是最少步数,BFS是通过层次的顺序来遍历的,因此可以从起点S开始计数遍历的层数,那么在到达终点T时的层数就是需要求解的起点S到达终点T的最少步数。

#include<iostream>
#include<queue>
using namespace std;
struct node
{
	int x;
	int y;//位置x,y 
	int step;//step为起点s到此位置所需步数 
}S, T, p;//p为临时节点 
int m, n;
char  s[100][100];
bool inq[100][100] = { false };
int d[4][2] = { 0,1,0,-1,1,0,-1,0 };
bool test(node t)//检验此节点是否有效 
{
	if (t.x<0 || t.y<0 || t.x >= m || t.y >= n || s[t.x][t.y] == '*' || inq[t.x][t.y] == true)return false;//越界,墙壁,已经入过队 
	return true;//有效位置 
}
int bfs()
{
	int i;
	queue<node> t;//定义队列 
	node top;//记录队首元素 
	t.push(S);//起点入队 
	inq[S.x][S.y] = true;
	while (!t.empty())
	{
		top = t.front();//取出队首元素 
		t.pop();//队首元素出队 
		if (s[top.x][top.y] == 'T')return top.step;//终点,返回最少步数 
		for (i = 0; i<4; i++)//四个方向 
		{
			p.x = top.x + d[i][0];
			p.y = top.y + d[i][1];
			if (test(p))//如果位置有效 
			{
				p.step = top.step + 1;//相对于上一层的元素(队首),步数加1 
				t.push(p);
				inq[p.x][p.y] = true;//设置为已入过队 
			}
		}
	}
	return -1;
}
int main()
{
	cin >> m >> n;
	getchar();
	for (int i = 0; i<m; i++)
		gets(s[i]);
	cin >> S.x >> S.y >> T.x >> T.y;//起点和终点坐标 
	S.step = 0;//初始化层数为0 
	cout << bfs();
}
inq数组的含义是判断节点是否已经入过队,而不是节点是否已被访问过(保证了最短路径),区别在于:如果设置成是否已被访问过,有可能在某个节点正在队列中(但还未访问)时由于其他节点可以到达它而将这个节点再次入队,导致很多节点反复入队,计算量大大增加。因此BFS中让每个节点只入队一次,故需要设置inq数组的含义为节点是否已经入过队而非节点是否已被访问。

当STL用queue时,元素入队的push操作只是制造了该元素的一个副本入队,因此入队后对该元素修改不会影响队列中的副本,而对队列中副本的修改也不会改变原元素;

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值