Bfs 逃脱(牛客网)
题目:
输入描述:
第一行输入一个整数t,表示一共的测试数据组数。 第二行输入两个整数n,m,表示幼儿园的大小。 接下来n行,每行m个字符,表示此格子是什么元素。 t<=200 3<=n<=30 3<=M<=30 保证图中有一个起点,一个出口,一个火灾源处.
输出描述:
每组数据输出一行,如果两人能够成功到达出口,那么输出最短逃离时间,否则输出T_T
输入
3 5 5 *.... ..... ..S#. ...E. ..... 5 5 ...#* ..#S# ...## ....E ..... 5 5 ..... S.... ..*#. ...E. .....
输出
2 T_T T_T 解析: 这题乍一看挺简单(确实挺简单),但本人尝试多次竟然没有AC,异常难受~ o(TωT)o 一开始的思路(有误,写给自己的,可以略过):存图,然后将小盆友和火同时Bfs,嗯就是这里出问题了,火焰和人的拓展条件并不一样,所以,在入队的数量并不同,SO拓展并不是同步的!!_φ(❐_❐✧ 人丑就要多WA 接着在网上找了个正解(https://www.cnblogs.com/zhgyki/p/9568761.html),模仿着自己写了一个,理一下其思路:将火焰的拓展和人的拓展分隔开,先将火焰拓展,利用时间作为之后的比较中介,将火焰到达每个点的时间记录在该点(这个思路如此牛*)。接着是人的Bfs,注意遇到出口时,时间小于或等于该点火焰蔓延到的时间即可(题目说明了火焰蔓延是后滞的),然后普通的逃脱到的点的时间要严格小于火焰到达的时间。 正解:
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 using namespace std; 5 typedef long long ll; 6 #define maxn 35 7 #define Inf 0x7fffffff 8 int n=0,m=0,ans=Inf; 9 int t=0; 10 char Map[maxn][maxn]; 11 bool vis[maxn][maxn]={0}; 12 int fir[maxn][maxn]={0};//记录fire到每一格所需时间 13 int dir[][2]={ 14 {1,0},{-1,0},{0,1},{0,-1}, 15 {1,1},{-1,-1},{-1,1},{1,-1} 16 }; 17 struct Point{ 18 int x,y,tm; 19 Point(){tm=0;} 20 Point(int a,int b,int c):x(a),y(b),tm(c){} 21 }fi,st; 22 void FireGo() 23 { 24 memset(vis,false,sizeof(vis)); 25 memset(fir,0,sizeof(fir)); 26 queue<Point> q; 27 q.push(fi); 28 vis[fi.x][fi.y]=true; 29 while(q.size()) 30 { 31 Point head=q.front(); 32 q.pop(); 33 for(int i=0;i<8;++i) 34 { 35 int nx=head.x+dir[i][0]; 36 int ny=head.y+dir[i][1]; 37 if(nx<0||nx>=n||ny<0||ny>=m) continue; 38 if(vis[nx][ny]) continue; 39 vis[nx][ny]=true; 40 fir[nx][ny]=head.tm+1;//计算每个点有火势蔓延到的时间 41 q.push({nx,ny,head.tm+1}); 42 } 43 } 44 } 45 bool Bfs() 46 { 47 memset(vis,0,sizeof(vis));//重新初始vis数组 48 queue<Point> q; 49 q.push(st); 50 vis[st.x][st.y]=true; 51 while(q.size()) 52 { 53 Point head=q.front(); 54 q.pop(); 55 for(int i=0;i<4;++i) 56 { 57 int nx=head.x+dir[i][0]; 58 int ny=head.y+dir[i][1]; 59 if(nx<0||nx>=n||ny<0||ny>=m) continue; //越界 60 if(vis[nx][ny]) continue; 61 if(Map[nx][ny]=='#') continue; 62 if(Map[nx][ny]=='E' &&head.tm+1<=fir[nx][ny])//先到出口,火才到 63 { 64 //vis[nx][ny]=true; 65 //q.push({nx,ny,head.tm+1}); continue; 66 ans=head.tm+1; 67 return true; 68 } 69 if(head.tm+1<fir[nx][ny]){//要严格小于,==时本秒结束火就到 70 vis[nx][ny]=true; 71 q.push({nx,ny,head.tm+1}); 72 } 73 74 } 75 } 76 return false; 77 } 78 int main() 79 { 80 cin>>t; 81 while(t--) 82 { 83 cin>>n>>m; 84 for(int i=0;i<n;++i) 85 for(int j=0;j<m;++j) 86 { 87 cin>>Map[i][j]; 88 if(Map[i][j]=='S'){ 89 st.x=i; st.y=j; 90 } 91 else if(Map[i][j]=='*'){ 92 fi.x=i; fi.y=j; 93 } 94 } 95 FireGo(); 96 if(Bfs()) cout<<ans<<endl; 97 else cout<<"T_T"<<endl; 98 } 99 return 0; 100 }
View Code
错解:
1 #include <iostream> //不能将火 和人同时bfs()两者的拓展条件不同,入队的数量不同,导致拓展不同步 2 #include <queue> 3 #include <cstring> 4 using namespace std; 5 int n=0,m=0; 6 char Map[30][30]={0}; 7 bool vis[30][30]={0}; 8 bool judge[30][30]={0}; 9 struct Point{ 10 int x,y,tm; 11 Point(){ x=0; y=0; tm=0; } 12 Point(int a,int b,int c){ x=a; y=b; tm=c; } 13 }fi,en,st; 14 int dir[][2]={ 15 {0,1},{1,0},{0,-1},{-1,0}, 16 {1,1},{-1,-1},{1,-1},{-1,1} //斜方向 17 }; 18 bool Check(int x,int y)//该点8方都不能有火源才安全 19 { 20 for(int i=0;i<8;++i) 21 { 22 if(Map[x+dir[i][0]][y+dir[i][1]]=='*') 23 return false; 24 } 25 return true; 26 } 27 int bfs()//fire 和 人同时移动 28 { 29 memset(vis,false,sizeof(vis)); 30 memset(judge,false,sizeof(judge)); 31 queue<Point> q; 32 st.tm=0; 33 q.push(st); 34 vis[st.x][st.y]=true; 35 while(!q.empty()) 36 { 37 Point head=q.front(); 38 q.pop(); 39 for(int i=0;i<4;++i) //四方向遍历 40 { 41 int nx=head.x+dir[i][0]; 42 int ny=head.y+dir[i][1]; 43 if(nx<0||nx>=n||ny<0||ny>=m) continue; //越界 44 if(Map[nx][ny]=='E') return (head.tm+1); //到达出口 45 if(vis[nx][ny]) continue; 46 if(Map[nx][ny]=='#'||Map[nx][ny]=='*') continue; //墙 火 47 if(!Check(nx,ny)) continue; //到达的点不安全 48 vis[nx][ny]=true; 49 q.push({nx,ny,head.tm+1}); 50 } 51 if(q.empty()) return 0; 52 //火势蔓延 53 for(int i=0;i<8;++i)//这里出错,火的蔓延也应要用到队列不然其实并未伸展 54 { 55 int nx=fi.x+dir[i][0]; 56 int ny=fi.y+dir[i][1]; 57 judge[nx][ny]=true; 58 if(nx<0||nx>=n||ny<0||ny>=m) continue; //越界 59 if(judge[nx][ny]) continue; 60 if(Map[nx][ny]=='E') return 0; //出口被烧 61 Map[nx][ny]='*'; 62 } 63 } 64 return 0; 65 } 66 int main() 67 { 68 int t=0; 69 cin>> t; 70 while(t--) 71 { 72 cin>> n>> m; 73 for(int i=0;i<n;++i) 74 for(int j=0;j<m;++j) 75 { 76 cin>> Map[i][j]; 77 if(Map[i][j]=='E'){ 78 en.x=i; en.y=j; 79 } 80 else if(Map[i][j]=='*'){ 81 fi.x=i; fi.y=j; 82 } 83 else if(Map[i][j]=='S'){ 84 st.x=i; st.y=j; 85 } 86 } 87 int temp=bfs(); 88 if(temp) cout<<temp<<endl; 89 else cout<<"T_T"<<endl; 90 } 91 return 0; 92 }
View Code
转载于:https://www.cnblogs.com/GorgeousBankarian/p/10380705.html
Bfs 逃脱(牛客网)相关推荐
- 牛客网挑战赛24 青蛙(BFS)
链接:https://www.nowcoder.com/acm/contest/157/E 来源:牛客网 有一只可爱的老青蛙,在路的另一端发现了一个黑的东西,想过去一探究竟.于是便开始踏上了旅途 一直 ...
- 牛客网 - 小乐乐打游戏(BFS)
链接:https://ac.nowcoder.com/acm/contest/301/G 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536 ...
- 牛客网平台常州大学新生寒假训练会试
A-添加逗号 链接:https://www.nowcoder.net/acm/contest/78/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其 ...
- 牛客网【每日一题】7月8日 Alliances
来源:牛客网 文章目录 题目描述 题解: 代码: 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld ...
- 【转自牛客网】C++类职位校招
作者:./a.out 链接:https://www.nowcoder.com/discuss/14022 来源:牛客网 话说在牛客网上混迹了半年,也没啥拿的出手的贡献.现在基本上自己的校招生涯要告一段 ...
- 今日头条后端面经总结(2018.12月)(转自牛客网)
面经(后端): 一 操作系统中的进程和线程还有虚拟存储. 计算机网络TCP和UDP仔细看一下,也不要放过滑动窗口; 还有计算机网络体系结构各层都要熟悉. lambda表达式 spring 智力题,比如 ...
- 【2020牛客网笔试整理】小红书笔试题
薯队长写了一篇笔记草稿,请你帮忙输出最后内容. 1.输入字符包括,"(" , ")" 和 "<"和其他字符. 2.其他字符表示笔记内容 ...
- 牛客网 2018校招真题 美团点评 重要节点
Description 牛客网 2018校招真题 重要节点 Solving Ideas BFS 创建一个标记数组arrive,arrive[i][j]为true表示从i可以到达j, false则不能 ...
- 算法记录 牛客网 leetcode刷题记录
算法记录 & 牛客网 & leetcode刷题记录 解题思路 STL容器 常用算法模板 堆排序 插入排序 快速排序 BFS层序遍历 二叉树 JZ55 二叉树的深度 BST(binary ...
- [C++] 牛客网:合并两个有序的数组
主要是体验一下牛客网里的核心代码模式到底是怎么弄的..还有C++这个东西平常用的太少了,试一试. 以外的还体验到了sort()函数的使用. 来源:牛客网 题目链接:合并两个有序的数组 知识点:数组.双 ...
最新文章
- linux的子进程和父进程,[Linux进程]在父进程和子进程中分别对文件进行操作
- python 递归乘法
- 简单讲解一下负载均衡、反向代理模式的优点、缺点
- 关闭Vue计算属性自带的缓存功能
- matlab计算曲线形心,并将y轴移动到形心上,使图形居中布置
- 文件操作(上传,下载,限制)
- idea2020.1使用Lombok注解,点击运行项目提示找不到get,set方法?
- 10 SystemVerilog语言编写SPI发送
- android volley设置编码,Volley 概览 | Android 开发者 | Android Developers
- html当当网上书店,当当网上书店案例代码+css+js+images
- Python压缩解压–zipfile
- ansys与solidworks关联失败,将SolidWorks模型导入ansys划分网格总是提示错误
- Windows10使用diskpart分区
- pc机 串口 并口 com口 详解
- 11_05.【Java】线程安全与线程同步
- 软件测试方法口诀,自测记忆法
- Vue - 加载静态图片的方式
- pandorabox安装迅雷远程下载插件
- c语言字符串dna,转录流程(c语言编写DNA转录程序)
- spring事务的传播行为的讲解(笔记 侵删)