受这个视频启发:
地图上各个坐标点距离起点的depth直接封装在Pos里面就可以了,省得还要建一个二维矩阵对应地图上每个点的depth。
而且,不需要用来之前那个定理一,因为BFS搜索到终点的时候,路径一定是最短的。因为BFS是一层一层往外扩张的,不是一条路走下去的。
#include <queue>
#include <memory>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
const int MAX_SIZE = 25;
const int INF_INT = 0x3f3f3f3f;
//用点来走迷宫,有面向对象那味,比较好写。如果单纯记录坐标,就很不直观,变量会很多。
struct Pos
{
int x, y;
int depth;
//关系运算符重载,判等
bool operator == (const Pos& rhs) const
{
return x == rhs.x && y == rhs.y;
}
bool operator != (const Pos& rhs) const
{
return !(*this == rhs);
}
};
//判断是否跑出边界
bool inside_judge(const Pos& pos, int n, int m)
{
return 0 <= pos.x && pos.x < n && 0 <= pos.y && pos.y < m;
}
int bfs(const Pos& src, const Pos& sink, int n, int m, int maze[][MAX_SIZE])
{
const int dir[4][2] = { {-1, 0}, {0, -1}, {1, 0}, {0, 1} }; //定义四个方向 也可以写两个一维数组,只要能实现改变横纵坐标就行
queue<Pos> que; //广度优先的那个队列,起始点入栈
que.push(src);
int Is_visit[100][100];
memset(Is_visit, 0, sizeof(Is_visit)); //把是否已访问都置为0
while (!que.empty())
{
Pos now = que.front();
que.pop();
if (now == sink) //重载的==
{
return now.depth; //即最短路径
}
//没到终点就继续搜索,广度优先,4次循环,四个方向都走一格,每走一格都计算一下附近的最短路径。而不是往一个方向钻。
//只要能走,就给他走一下
for (int ind = 0; ind < 4; ++ind)
{
Pos next = now;
next.x += dir[ind][0]; //设定下一个的坐标,有向上下左右4种可能,都改变一下坐标看看有没有越界、是不是0
next.y += dir[ind][1]; //dir[4][2] = { {-1, 0}, {0, -1}, {1, 0}, {0, 1} };
//dir[4][2]的顺序为【左上右下】,所以一开始往下走,dp[0][-1]=1,然后(0,-1)这个点入队列
//然后回来,再初始化next结点为now,再往右走,dp[1][0]=1,然后(1,0)这个点入队列。
//然后这个for循环就结束了,回到while循环,判断队列不空,拿到队首元素(0,-1),继续上述操作
/* 2 0 0
0 0 1
3 0 1*/ //这就是maze的本尊
if (inside_judge(next, n, m) && Is_visit[next.x][next.y] == 0 && maze[next.x][next.y] == 0)
{
Is_visit[next.x][next.y] = 1;
next.depth = now.depth + 1;
que.push(next);
}
}
}
return -1; //如果在上面没能return成功,就出while循环,返回-1
}
void incubate()
{
int n, m;
int maze[MAX_SIZE][MAX_SIZE];
/* 2 0 0
1 0 1
3 0 1*/ //maze填入数据后,就长这样
Pos src, sink; //起点和终点
int ans;
while (cin >> n >> m) //这是什么骚操作?
{
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
cin >> maze[i][j];
}
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
switch (maze[i][j]) //寻找起始和终点
{
case 2: src.x = i, src.y = j, src.depth = 0, maze[i][j] = 1;
break;
case 3: sink.x = i, sink.y = j, maze[i][j] = 0;
break;
default:
break;
}
}
}
ans = bfs(src, sink, n, m, maze);
if (-1 == ans)
{
cout << "Disconnected!" << endl;
}
else
{
cout << "The miminum distance from start point to target point is"
<< ans << endl;
}
}
return;
}
int main(int argc, char* argv[])
{
incubate();
return 0;
}
/*
测试数据:
connected
3 3
2 0 0
1 0 1
3 0 1
connected
3 3
2 0 0
0 0 1
3 0 1
disconnected
3 3
2 0 0
1 1 1
3 0 1
*/