POJ 3669 Meteor Shower 流星雨 解题思路心得 BFS广搜 C/C++AC代码(另有TLE不知其因)
原题
http://poj.org/problem?id=3669
题意
贝西(Bessie)听说即将发生一场异常的流星雨;有报道称这些流星将坠入大地并摧毁其所击中的任何东西,为安全着急,她发誓要找到一个安全的地方(一个从未被流星摧毁的路)。
她目前正在坐标平面上的原点放牧,并希望移至新的更安全的位置,同时避免沿途被流星摧毁。
报告说,在时间Ti(0≤Ti≤1,000)时,M个流星(1≤M≤50,000)将撞击,流星i将撞击点(Xi,Yi)(0≤Xi≤300; 0≤Yi≤300)。
每个流星都会破坏其撞击的点以及四个直线相邻的晶格点。
贝西在时间0离开原点,并且可以以每秒一个距离单位的速度在第一象限中平行于轴移动,到达尚未被流星破坏的任何(通常为4个)相邻直线点。
在大于或等于销毁时间的任何时间位于一个点上)。
确定Bessie到达安全地点所需的最短时间。
输入值
*第1行:单个整数:M
*第2…M + 1行:第i + 1行包含三个以空格分隔的整数:Xi,Yi和Ti
输出量
*第1行:贝西到达安全地点所需的最短时间;如果不可能,则为-1。
Sample Input
4
0 0 2
2 1 2
1 1 2
0 3 5
Sample Output
5
思路
最短存活时间,用BFS 起点为(0,0),终点为安全地带。
m[][]表示各个地方被流星雨轰炸的时间,初始化为INF,即安全,输入的同时对其进行初始化,特别注意,因爆炸波及5个单位,爆炸区域可能存在重叠,并且刚好爆炸和爆炸后都无发进入,所以t[]总是取最小的爆炸时间点。
AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=1<<30;
int M,maze[388][388];
int d[5][2]={{0,0},{0,1},{1,0},{0,-1},{-1,0}};
typedef struct {int x,y,t;
}node;
int in(int x,int y){return x>=0&&y>=0;
}
int bfs()
{queue <node> que;if(maze[0][0]>0) que.push(node{0,0,0});while(!que.empty()){node cur=que.front();que.pop();int &x=cur.x,&y=cur.y,&t=cur.t;if(maze[x][y]==INF) return t;for(int i=1;i<5;i++){int nx=x+d[i][0],ny=y+d[i][1];//不越界 且 到下一格的时间比爆炸时间早 if(in(nx,ny)&&t+1<maze[nx][ny]){//防止回退 if(maze[nx][ny]!=INF) maze[nx][ny]=t+1; que.push(node{nx,ny,t+1});}} }return -1;
}
void solve()
{int ans=bfs();printf("%d\n",ans);
}
int main()
{void solve();scanf("%d",&M);fill(maze[0],maze[0]+388*388,INF);while(M--){int x,y,t;scanf("%d %d %d",&x,&y,&t);for(int i=0;i<5;i++){int nx=x+d[i][0],ny=y+d[i][1];if(in(nx,ny)) maze[nx][ny]=min(t,maze[nx][ny]);}}solve();return 0;
}
参考一位大佬的代码:
https://blog.csdn.net/a1097304791/article/details/101617157
TLE代码 大佬看出哪有问题请不吝赐教
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
#define ff first
#define ss second
using namespace std;
typedef pair<int,int> P;
int M,ans,m[400][400],d[400][400];//m[]用来存放各个地点被炸时间 d[]用来存放从原点到对应位置所需时间
int x[50100],y[50100],t[50100];//记录每一颗流星爆炸坐标x,y及时间t 参考他人代码得知也可用结构体
int move[5][2]={0,1,1,0,0,-1,-1,0,0,0};//右下左上[本身] 这里顺序 下面有一处需要5个 有一处需要移动只需4个
int main()
{void solve();int in(int x,int y);memset(m,0x3f,sizeof(m));scanf("%d",&M);for(int i=0;i<M;i++){scanf("%d %d %d",&x[i],&y[i],&t[i]);for(int j=0;j<5;j++)//需要5个 写入m[][] {int &dx=move[j][0];int &dy=move[j][1];if(in(x[i]+dx,y[i]+dy)&&m[x[i]+dx][y[i]+dy]>t[i])//★★注意:输入数据时,要考虑该点及附近的四个点对应的时间是否小于新输入的时间,若小于则无需改动,反之,改变这五个点对应的时间m[x[i]+dx][y[i]+dy]=t[i];//m[][]中 INF==安全 !INF==不安全 ★小心越界问题★}}solve();return 0;
}
void solve()
{int bfs();ans=bfs();printf("%d\n",ans);
}
int bfs()
{int in(int x,int y);int boom(int x,int y,int tt);if(m[0][0]==0)//★★如果m[0][0]在时间0时就爆炸 那么她永远也到达不了【存活】的【真实】 return -1;queue <P> que;que.push(P(0,0));d[0][0]=0;while(que.size()){P p=que.front();que.pop();if(m[p.ff][p.ss]==INF)//到达安全地带return d[p.ff][p.ss];for(int i=0;i<4;i++)//这里只需4个 (0,0)不算移动 {int &dx=move[i][0];int &dy=move[i][1];int nx=p.ff+dx;int ny=p.ss+dy;if(in(nx,ny)&&!boom(nx,ny,d[p.ff][p.ss]+1)) //能走的条件:不越界 且 下一秒到达的位置 不会被炸 {que.push(P(nx,ny));d[nx][ny]=d[p.ff][p.ss]+1;}}}return -1;//当queue中无元素时 还会被炸 则逃跑失败
}
int boom(int xx,int yy,int tt)//点(xx,yy)在tt时是否会被炸 默认(xx,yy)不越界
{int in(int x,int y);for(int i=0;i<M;i++)//判断 此不安全地 此时 是否会被炸 (注:此地默认不是安全地带 bfs前段:如安全就结束了){for(int j=0;j<5;j++)//我他喵的i++看了1小时没看出来 艹 {int &dx=move[j][0];//定义 引用 int &dy=move[j][1];//爆炸中心是自己输入的 不可能越界if(in(x[i]+dx,y[i]+dy))//★小心越界问题★ {if((xx==x[i]+dx)&&(yy==y[i]+dy)&&(tt>=m[xx][yy]))//注意 return 1;}} }return 0;
}
int in(int x,int y)
{if(x>=0&&x<400&&y>=0&&y<400)return 1;return 0;
}
总结
①输入输出尽量使用scanf/printf,不用cin/cout,因前者运行效率高,如用后者易TLE
②移动向量可以加(0,0)表示本身,本题中m[][]初始化时需要
③int &dx=move[j][0] dx是引用,别名
④本题当初始化m[][]时,特别要注意爆炸区域会重叠,所以每一块的值应为最早爆炸时间
⑤使用方向移动向量时特别要注意数组越界问题
⑥本题还需注意当(0,0)在t=0时被轰炸,她远也到达不了【存活】的【真实】
⑦i,j看清楚别眼花
⑧TLE可能原因:总结①;没有防止回退(可以用vis[]标记)那位大佬代码里注释的最佳化剪枝应该也是起这个作用;?代码开了太多数组(代码不够简洁精妙)?待定
POJ 3669 Meteor Shower 流星雨 解题思路心得 BFS广搜 C/C++AC代码(另有TLE不知其因)相关推荐
- POJ 3669 Meteor Shower
暴力DFS. 有2个剪枝: 1.记录一下走到某一格的最小步数 2.走到安全地点马上return WA点:安全地点坐标不一定在300以内! #include<cstdio> #include ...
- bzoj 1611: [Usaco2008 Feb]Meteor Shower流星雨(DP)
1611: [Usaco2008 Feb]Meteor Shower流星雨 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 1631 Solved: 6 ...
- 洛谷 P2895 [USACO08FEB]Meteor Shower S C++ BFS 广搜
题目描述 Bessie hears that an extraordinary meteor shower is coming; reports say that these meteors will ...
- python四位玫瑰数的解题思路_入门python知识点总结以及15道题的解题思路分析
知识点总结python 1.序列app 操做符ide x in s 若是x是列表s的元素,返回True,不然False s + t 链接两个序列s和t s*n或者n*s 将序列s复制n次 s[i] 返 ...
- PTA寒假基础题训练(含解题思路)(中)
目录 7-19 两个有序单链表求差集 AC代码: 7-20 统计数字字符和空格 AC代码: 7-21 打印沙漏 AC代码: 7-22 Wifi密码 AC代码: 7-23 福到了 AC代码: 7-24 ...
- 【POJ - 3669】Meteor Shower(bfs)
-->Meteor Shower 直接上中文了 Descriptions: Bessie听说有场史无前例的流星雨即将来临:有谶言:陨星将落,徒留灰烬.为保生机,她誓将找寻安全之所(永避星坠之地) ...
- 玉米迷宫,Meteor Shower S,单词接龙
玉米迷宫:- [P1825 [USACO11OPEN]Corn Maze S](https://www.luogu.com.cn/problem/P1825) 这是让我卡了整整一天的题目,虽然说思路不 ...
- 高分选手讲解:如何突破思维圈限,从NLP角度挖掘新的解题思路
稳居排行榜前三,成绩高达1.453292的他,究竟是位怎样的神级选手?今天,我们就邀请到这位实力强劲的神秘大咖,为大家揭晓他的上分思路. 实力选手在线指导,火速报名与他PK一下吧!5月31日算法大赛报 ...
- 大神干货:冠军选手分享解题思路,助你轻松突围初赛
2020年腾讯广告算法大赛的初赛的帷幕已然拉开,新老选手们正面临着全新数据集的挑战.在大家努力刷分的紧张时刻,我们为大家邀请到2019年腾讯广告算法大赛冠军.数据竞赛爱好者,也是本次大赛的参赛选手-- ...
最新文章
- 鸿蒙系统开发者公测,公测尝鲜开启!华为Mate40/P40开始和安卓渐行渐远
- BZOJ 1878 HH的项链
- 03-spring bean
- cookie的细节——1.一次可不可以发送多个cookie?2. cookie在浏览器中保存多长时间?3. cookie能不能存中文?4. cookie共享问题?
- 基于阿里云镜像源使用kubeadm安装k8s单master节点集群(v1.17.3)
- 安卓 spinner下拉框 做模糊查询_SEO数据查询工具
- Qcon2017实录|Service Mesh:下一代微服务
- 分布式优化和去中心化优化概述
- 球面投影全景图快速拼接
- 20165107 网络对抗技术 Exp4 恶意代码分析
- 如何进入Github【亲测有效】
- 第十三届蓝桥杯大赛软件赛省赛 Python 大学 B 组
- 旷视科技——身份验证、活体检测、人脸比对
- java.lang.NoClassDefFoundError: org/jdom2/JDOMException
- 第二十章 指针 二 为指针分配和释放空间(转)
- 记微信开发者工具登录网络连接失败
- OpenCV学习(二十三) :模板匹配:matchTemplate(),minMaxLoc()
- via浏览器 html代码,网页黑色加强的css代码
- IBM Rational software Architect 9.0安装包百度网盘
- 70道Dubbo面试题及答案(最新整理)