超详细题解
2024-06-10 15:35:21
发布于:上海
12阅读
0回复
0点赞
#include<iostream>
#include<queue>//导入queue头文件用于实现广搜
using namespace std;//使用命名空间std
int n,m,s=2147483647;//开两个变量n和m表示矩阵的深度和宽度,s变量存储最少路径,初始化为int最大值
int sx,sy,ex,ey;//开两个变量sx和sy存储开始节点的坐标,另开两个变量ex和ey存储结束节点的坐标
int dir[4][2]={1,0,0,1,-1,0,0,-1};//方向数组,因为它可以向上下左右四个方向移动,故用一个大小为4x2的二维数组
//当然,诸位也可以用pair<int,int> dir[4]来存储,但是记得导入头文件utility
int map[9][9];//开一个二维数组存储地图
struct node{
int x,y,hp,steps;//结构体成员中,x和y表示节点坐标,hp表示当前hp(血量),steps表示已经走过的路程
};//考虑使用结构体队列完成广搜
queue<node>q;//使用结构体队列完成广搜
bool vis[9][9];//开一个bool类型的二维数组,标记这个地方有没有走过
//由于广搜的特性是同一深度的点一次性都存到队列中,所以下边vis数组中一个节点一旦被标记为1就不会变回0
void bfs(){//定义一个广搜(bfs)函数
q.push({sx,sy,6,0});//把第一个节点存入数组,此时初始血量为6,走过的路程为0
vis[sx][sy]=1;//将此节点标记为1
while(!q.empty()){
node f=q.front();//获取首个节点进行搜索
q.pop();//首个节点出队列
//【题外话】如果不出队列,那么会死循环,导致TLE或者MLE,那么就糟糕了
if(f.x==ex&&f.y==ey)s=min(f.steps,s);//判断是否到达家里,如是,那么更新s为s和f.steps中较小的那个数值
for(int i=0;i<4;i++){//遍历方向数组
int nx=dir[i][0]+f.x,ny=dir[i][1]+f.y;//根据方向数组和当前的坐标确定新节点的坐标
if(nx>=0&&nx<n&&ny>=0&&ny<m&&!vis[nx][ny]&&map[nx][ny]&&f.hp>1){//判断是否能够到达新节点而且血量是否足够
vis[nx][ny]=1;//将新节点标记
q.push({nx,ny,map[nx][ny]==4?6:f.hp-1,f.steps+1});//将新节点存入队列,以便于下一轮广搜
//这里hp使用三目运算符来计算,如果新节点值为4,那么说明这里有鼠标,前提是当前格时血量>1,否则走到鼠标位置血量清零失败
//如果到达新节点还有血量且新节点值为4,那么回血直至回满封顶;如果新节点到达时还有血量而且节点值为非零整数,那么扣一格血
}
}
}
}
int main(){//主函数
cin>>n>>m;//输入矩阵大小
for(int i=0;i<n;i++)for(int j=0;j<m;j++){//循环输入每一个节点的大小
cin>>map[i][j];//输入每一个节点
if(map[i][j]==2)sx=i,sy=j;//判断是否为起始节点
if(map[i][j]==3)ex=i,ey=j;//判断是否为终止节点
}
bfs();//调用广搜函数
cout<<(s==2147483647?-1:s);//由于初值为2147483647,如果s变量现在还是这个值,说明没有到达家里,输出-1,否则输出s的值
return 0;//结束主函数
}
打字不易,点个赞鼓励一下吧!
如感兴趣,加入团队吧
这里空空如也
有帮助,赞一个