当前位置: 首页 > news >正文

一次可连续走k步的bfs的处理方法

做在二维地图上移动的模拟题时,绝大多数情况都需要使用 \(bfs\),其中 \(99\%\) 的情况都是只走一步(也就是上下左右四个方向选一个,并移动一格)。那么如果每一次可以连续走 \(k\) 步,我们应当如何处理呢?

M - Nightmare Ⅱ

重点看 bfs 函数部分,将 \(while\) 函数的退出条件改成了计数器减为 0。这样就可以做到在 bfs 的每一步转移时,用到的都是上一次走了相同步数的点。

本题也是练习双向 bfs 的好题。通过按照时间戳 cnt 同时模拟两个人的 bfs 过程,判断两个人是否可以相遇 当且仅当 两个人可以在某 cnt 时走到同一个点上。而与鬼魂的相遇直接简单地利用曼哈顿距离处理。

#include<algorithm>
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
struct str
{int x,y;
}z[2],b,g;
int t,n,m,cnt;
int drt[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
char mapp[801][801];
bool vis[2][801][801];
queue<str> que[2];
bool check(str t)
{bool flag=true;if(abs(t.x-z[0].x)+abs(t.y-z[0].y)<=2*cnt)//判断鬼是否已经到达某一点flag=false;else if(abs(t.x-z[1].x)+abs(t.y-z[1].y)<=2*cnt)flag=false;if(t.x<0||t.y<0||t.x>=n||t.y>=m)//判断即将要走的点是否在界外 flag=false;else if(mapp[t.x][t.y]=='X')flag=false;return flag; 
}
bool bfs(int x)
{int tot=que[x].size();//每次连续弹出、处理的点都是同一步的点str now,nxt;while(tot--) // !!! 精妙之处,固定弹出队列元素的数量。设当前是在模拟走连续k步中的第j步,则弹出的点一定是恰好走了j-1步的所有点。等到处理完这些点后,队列内存留的是所有恰好走了j步的点,形成递推关系。{now=que[x].front();que[x].pop();if(!check(now))//判断鬼是否已经到达now所在的点continue;for(int i=0;i<4;i++){nxt.x=now.x+drt[i][0];nxt.y=now.y+drt[i][1];if(check(nxt)&&!vis[x][nxt.x][nxt.y])//判断nxt所在的点是否出界、是否已经过{vis[x][nxt.x][nxt.y]=true;if(vis[x][nxt.x][nxt.y]&&vis[1-x][nxt.x][nxt.y])//判断nxt所在的点是否被G和M都走过return true;que[x].push(nxt);}}}return false;
}
int fun()
{while(!que[0].empty())//每次处理一组新的数据前先将队列清空que[0].pop();while(!que[1].empty())que[1].pop();memset(vis,0,sizeof(vis));que[0].push(b);que[1].push(g);vis[0][b.x][b.y]=vis[1][g.x][g.y]=true;while(!que[0].empty()||!que[1].empty()){cnt++;//统计时间for(int i=0;i<3;i++)//M每个单位时间走三步if(bfs(0))return cnt;if(bfs(1))//G每个单位时间走一步return cnt;}return -1;
}
int main()
{scanf("%d",&t);while(t--){int zx=0;cnt=0;scanf("%d%d",&n,&m);for(int i=0;i<n;i++){scanf("%s",&mapp[i]);for(int j=0;j<m;j++){if(mapp[i][j]=='Z'){z[zx].x=i,z[zx].y=j;zx++;}if(mapp[i][j]=='M')b.x=i,b.y=j;if(mapp[i][j]=='G')g.x=i,g.y=j;}}printf("%d\n",fun());}return 0;
}
http://www.jsqmd.com/news/298994/

相关文章:

  • SCI论文,能引用中文参考文献吗?
  • Spring 6.0基于JDB手写定制自己的ROM框架
  • 一个英语听力的神器——获取transcripts
  • 基于SpringBoot完成的垃圾分类管理系统
  • 2026年国内评价高的调节阀厂家哪家强,半球阀/截止阀/闸阀/不锈钢阀门/电动盲板阀/消声止回阀,调节阀生产厂家排行榜
  • 机器学习系列
  • 全方位谈判兵法——从底层逻辑到高手实战的20堂必修课
  • 个人职场顶层设计
  • 通过阅读实现认知跃迁
  • 人性皆有裂痕:理解人格的 52 堂心理学课
  • 心理边界完全指南:如何在快节奏世界中找到高效与舒适
  • 【计算机毕业设计案例】基于springboot的餐饮医院图书馆通用预约系统的设计与实现(程序+文档+讲解+定制)
  • 金华无尘车间改造优选,2026年洁净空间新体验,净化车间/净化工程/无尘室/无尘车间/恒温恒湿车间,无尘车间标准哪家好
  • 详细介绍:大型实时交易系统中基于事件驱动架构(EDA)构建高吞吐高可靠后端服务的工程实践与架构优化策略分享
  • Java毕设选题推荐:基于springboot+vue的通用预约系统的设计与实现基于Springboot校园实验室预约管理系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 计算机Java毕设实战-基于springboot的各类型通用预约系统的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 【毕业设计】基于springboot的通用预约系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • Java被裁后快速上岸指南!
  • Java行情何时触底反弹?
  • Flutter + OpenHarmony 顶部导航栏:AppBar 与自定义标题、操作按钮的多设备适配
  • Flutter + OpenHarmony 垂直列表:ListView 组件在手机上的性能优化实践
  • Flutter + OpenHarmony 网格布局:GridView 与 SliverGrid 在鸿蒙设备内容展示中的应用
  • Java毕设项目推荐-基于springboot+Java的各行通用预约系统的设计与实现【附源码+文档,调试定制服务】
  • 【从零手搓128GB显存GPU:我的节能能效探索之旅】
  • 互联网大厂Java面试实录:Spring Boot微服务在电商场景中的应用与挑战
  • 2026年纸箱封箱机选购指南:靠谱厂家一网打尽,智能码垛机/包装机/热收缩膜包装机/收缩膜包装机,纸箱封箱机厂商怎么选
  • 2026年行业内排行前列的高效粉碎机品牌怎么选择,高效粉碎机/高效包衣机/粉碎整粒机,高效粉碎机制造商哪个好
  • 计算机Java毕设实战-基于springboot+vue+mysql人脸识别的考勤管理系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • Java毕设项目:基于springboot的通用预约系统的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 计算机毕业设计hadoop+spark+kafka+hive漫画漫推荐系统 知识图谱 动漫可视化 动漫爬虫 大数据毕业设计(源码+文档+PPT+讲解)