1.实现思路:
我们定义一个距离矩阵d[][]记录所有位置到起始点的距离(需要的步数),
我们通过队列模拟bfs,得出所有位置到起始点的距离(需要的步数),也就是所有d[][]的元素值,于是d[n-1][m-1]就是要求的最小步数(d[0][0]是起始点)
我们用pair类型{x,y}表示在迷宫中的位置坐标,并用队列来存储这些坐标,模拟bfs过程,首先将起始坐标{0,0}入队,然后进入循环:当队列非空时,考虑队首元素,把该位置下一步能到达的位置全部入队,最后把队首元素出队。
我们在考虑某位置下一步能到达哪些位置的时候,我们需要考虑
1:该位置在迷宫数组mg[][]中值为0,表示可以走,不是墙壁
2:该位置得在迷宫矩阵坐标范围内,不能数组越界,即_0<=x<n,0<=y<m_
3:该位置没有被走过
我们自然会想到再定义一个和迷宫mg矩阵同类的book数组来记录每个位置有没有被走过。
但我们用距离矩阵d[][]就可以判断每个位置有没有走过,我们把d[][]所有元素初始化为-1,表示所有点没有被访问过,非负整数就表示该点到起始点距离。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110;
typedef pair<int,int> PII;
queue<PII> q;
int mg[N][N],d[N][N];//迷宫数组mg[][]读入题目所给迷宫,d[][]存储棋盘每个位置到起点的距离(走的步数)
int n,m;
int bfs()
{
d[0][0]=0;//(0,0)位置是起始点,距离为0
q.push({0,0});//先把起始坐标入队
while(q.size())//当队列非空
{
PII t=q.front();//考虑队首元素
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
for(int i=0;i<4;i++)//遍历每个迷宫位置下一步可以到达的位置
{
int x=t.first+dx[i],y=t.second+dy[i];
if(x>=0 && x<n && y>=0 && y<m && d[x][y]==-1 && mg[x][y]==0)
{
q.push({x,y});//把可以到达的所有位置入队
d[x][y]=d[t.first][t.second]+1;//写入该点处距离
}
}
q.pop();//队首出队
}
return d[n-1][m-1];
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>mg[i][j];
memset(d,-1,sizeof d);
cout<<bfs();
return 0;
}
常用函数和技巧
1.memset(void *s, int c, unsigned long n)
注意:对于整型数组,memset只能把一段空间值化为0或-1
功能:将指针变量 s 所指向的前 n 字节的内存单元用一个“整数” c 替换,
注意 c 是 int 型。s 是 void* 型的指针变量,所以它可以为任何类型的数据进行初始化。
例:将整型矩阵mg[n][m]所有元素初始化为-1 :memset(mg,-1,sizeof(mg))
2.memcpy(void *destination,const void *source, size_t num);
功能:从源source所指的内存地址的起始位置开始拷贝n个字节到目标destination所指的内存地址的起始位置中。
注意是把第二个参数的内容复制给第一个参数
例:将整型数组b前n个元素复制给a :memcpy(a,b,sizeof(int)*n)
3.遍历矩阵某元素的临近方位元素
比如要遍历a[x][y]上下左右的四个元素
我们可以把中心坐标(x,y)分别加上方向分量(0,1),(0,-1),(-1,0),(1,0),从而得到上下左右的坐标
实现过程如下:
int dx{4}={0,0,-1,1},dy[4]={1,-1,0,0};
for(int i=0;i<4;i++)
{
cout<<a[x+dx[i]][y+dy[i]]<<endl;
}