bfs 与优先队列————洛谷p1126(历经两个小时总算AC了,哭晕)
机器人搬重物
题目描述
机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径 \(1.6\) 米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个 \(N\times M\) 的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:
- 向前移动 \(1\) 步(
Creep
); - 向前移动 \(2\) 步(
Walk
); - 向前移动 \(3\) 步(
Run
); - 向左转(
Left
); - 向右转(
Right
)。
每个指令所需要的时间为 \(1\) 秒。请你计算一下机器人完成任务所需的最少时间。
输入格式
第一行为两个正整数 \(N,M\ (1\le N,M\le50)\),下面 \(N\) 行是储藏室的构造,\(0\) 表示无障碍,\(1\) 表示有障碍,数字之间用一个空格隔开。接着一行有 \(4\) 个整数和 \(1\) 个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东 \(\tt E\),南 \(\tt S\),西 \(\tt W\),北 \(\tt N\)),数与数,数与字母之间均用一个空格隔开。终点的面向方向是任意的。
输出格式
一个整数,表示机器人完成任务所需的最少时间。如果无法到达,输出 \(-1\)。
样例 #1
样例输入 #1
9 10
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0
7 2 2 7 S
样例输出 #1
12
本题是一个很典型的dfs题,但坑点很多,一连坑了我好多次。。。。不嘻嘻
- 首先就是计算转向的时间,我将NSWE是个方向代数为1,2,3,4,然后取他们差的绝对值,代表转向的时间,但是没有注意到4和1相差3,但实际上只用1秒,这个错纯属犯病。。。写太快了.
- 然后就是如何将输入的方格图转化为格点图,这个要画出图来
- 之后就是机器人走三步的时候有可能跳过障碍,但这是不允许的,所以需要剪枝
- 最后就是要用优先队列优先取出tm最小的节点
- 还有就是它测试用例的一些毒点,比如起点卡墙里(@-@!
具体细节在代码里
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<iomanip>
using namespace std;
int a[55][55]; //存储方格图
long long mp[55][55]; //存储格点图,即机器人行走的图
int dis[55][55]; //用于记录机器人到该格点的最短时间
int n, m; //方格图的尺寸
int x1, y11, x2, y2; //记录起点终点坐标
int sto;//起点的方向
string ch;//读入起点的方向
struct node
{
int x;
int y;//当前点的坐标
int to;//1=>N(上) 2=>E(右) 3=>S(下) 4=>W(左) 方向编号
int tm;//从起点到当前点的最短时间
bool operator < (node a)const {
return tm > a.tm;
}
//stl中优先队列默认优先取出最大值,所以要重载运算符,保证每次取出的都是代价最小的元素
};
priority_queue<node> que;//优先队列
node now, nxt;
int dx[] = { 0, -1,0,1,0 };
int dy[] = { 0, 0,1,0,-1 };
int abs(int a, int b) {
return a > b ? a - b : b - a;
}
int calchange(int now, int aft) {
//注意这个情况
if (abs(now, aft) == 3) {
return 1;
}
else {
return abs(now, aft);
}
}
void readto()
{
switch (ch[0])
{
case 'N': sto = 1; break;
case 'S': sto = 3; break;
case 'W': sto = 4; break;
case 'E': sto = 2; break;
}
return;
}
void change()
{
//把边框全部置为1,因为机器人有宽度,不能出现在那里
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
if (a[i][j] == 1)//如果当前格为障碍物,则它的四个顶点都不能走
{
mp[i + 1][j] = 1;
mp[i][j + 1] = 1;
mp[i + 1][j + 1] = 1;
mp[i][j] = 1;
}
if (i == 1 || j == 1) {
mp[i][j] = 1;
}
if (i == n || j == m) {
mp[i + 1][j + 1] = 1;
}
}
}
mp[n + 1][1] = 1;
mp[1][m + 1] = 1;
}
void bfs() {
dis[x1+1][y11+1] = 0;
node fir;
fir.x = x1+1;
fir.y = y11+1;
fir.to = sto;
fir.tm = 0;
que.push(fir);
int changecost = 0;
while (!que.empty()) {
now = que.top();
//这个是打印路径的代码
//cout << now.x << " " << now.y << " " << now.to << " " << now.tm << endl;
if (now.x == x2+1 && now.y == y2+1) break; //剪枝
que.pop();
if (now.tm > dis[now.x][now.y]) continue; //剪枝,这个可不加,好像没用
//遍历四个方向
for (int i = 1; i <= 4; i++) {
changecost = calchange(now.to, i);
//三种移动方式
for (int j = 1; j <= 3; j++) {
nxt.x = now.x + dx[i] * j;
nxt.y = now.y + dy[i] * j;
//if (mp[nxt.x][nxt.y] == 1 && j==1 || mp[nxt.x][nxt.y] == 1 && j == 2) break;
if (nxt.x <= 1 || nxt.x > n || nxt.y <= 1 || nxt.y > m || mp[nxt.x][nxt.y] == 1) break; //剪枝,这个边界判断最好对着图来
nxt.to = i;
nxt.tm = now.tm + 1 + changecost;
if (dis[nxt.x][nxt.y] > nxt.tm) {
dis[nxt.x][nxt.y] = nxt.tm;
que.push(nxt);
}
}
}
}
}
int main()
{
memset(dis, 1061109567, sizeof(dis));
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
scanf("%d", &a[i][j]);
}
}
cin >> x1 >> y11 >> x2 >> y2; //在c++中y1是个函数,所以要换一个
cin >> ch;
readto();//判断ch代表的方向
change();//把方格地图转化为机器人可以走的格点地图
//特判一下,防止依赖就卡墙,或者终点卡墙,这个起点和终点的索引最好对着图来
if (mp[x1 + 1][y11 + 1] == 1 || mp[x2+1][y2+1]==1) {
cout << -1;
return 0;
}
bfs();
//这个是打印格点图的代码,可以打印出来看看
/*for (int i = 1; i <= n + 1; i++) {
for (int j = 1; j <= m + 1; j++) {
cout << mp[i][j] << " ";
}
cout << endl;
}*/
if (dis[x2+1][y2+1] == 1061109567) {
cout << -1;
}
else {
cout << dis[x2 + 1][y2 + 1];
}
}
bfs 与优先队列————洛谷p1126(历经两个小时总算AC了,哭晕)的更多相关文章
- 洛谷 P1126 机器人搬重物 (BFS)
题目链接:https://www.luogu.org/problemnew/show/P1126 吐槽:这题很阴险 一开始没把格子图转化成点图:30分 转化成点图,发现样例过不去,原来每步要判断vis ...
- 洛谷P1126 机器人搬重物
洛谷1126 机器人搬重物 题目描述 机器人移动学会(RMI)现在正尝试用机器人搬运物品.机器人的形状是一个直径1.6米的球.在试验阶段,机器人被用于在一个储藏室中搬运货物.储藏室是一个N*M的网格, ...
- 洛谷P1126机器人搬重物[BFS]
题目描述 机器人移动学会(RMI)现在正尝试用机器人搬运物品.机器人的形状是一个直径1.6米的球.在试验阶段,机器人被用于在一个储藏室中搬运货物.储藏室是一个N*M的网格,有些格子为不可移动的障碍.机 ...
- 洛谷P1126 机器人搬重物【bfs】
题目链接:https://www.luogu.org/problemnew/show/P1126 题意: 给定一个n*m的方格,机器人推着直径是1.6的球在格子的线上运动. 每一秒钟可以向左转,向右转 ...
- 洛谷——P1126 机器人搬重物
P1126 机器人搬重物 题目描述 机器人移动学会(RMI)现在正尝试用机器人搬运物品.机器人的形状是一个直径1.6米的球.在试验阶段,机器人被用于在一个储藏室中搬运货物.储藏室是一个N*M的网格,有 ...
- 洛谷P4630 铁人两项--圆方树
一道很好的圆方树入门题 感谢PinkRabbit巨佬的博客,讲的太好啦 首先是构建圆方树的代码,也比较好想好记 void tarjan(int u) { dfn[u] = low[u] = ++dfn ...
- 洛谷 P1126 机器人搬重物
题目描述 机器人移动学会(RMI)现在正尝试用机器人搬运物品.机器人的形状是一个直径 $1.6 米的球.在试验阶段,机器人被用于在一个储藏室中搬运货物.储藏室是一个 N×MN \times MN×M ...
- 【洛谷P1126】机器人搬重物
题目大意:给定一个 N 行,M 列的地图,一个直径为 1.6 的圆形机器人需要从起点走到终点,每秒钟可以实现:向左转,向右转,向前 1-3 步.求从起点到终点最少要多长时间. 题解:相比于普通的走迷宫 ...
- 洛谷—— P1126 机器人搬重物
https://www.luogu.org/problem/show?pid=1126 题目描述 机器人移动学会(RMI)现在正尝试用机器人搬运物品.机器人的形状是一个直径1.6米的球.在试验阶段,机 ...
- 洛谷4630APIO2018铁人两项(圆方树+dp)
QWQ神仙题啊(据说是今年第一次出现圆方树的地方) 首先根据题目,我们就是求对于每一个路径\((s,t)\)他的贡献就是两个点之间的点数,但是图上问题我并没有办法很好的解决... 这时候考虑圆方树,我 ...
随机推荐
- 如何更好的使用 Windows
如何更好的使用 Windows Microsoft 辅助功能和工具 键盘快捷方式,常用 ctrl+C 复制 ctrl+V 粘贴 ctrl+X 剪切 ctrl+Z 撤销 ctrl+Y 回退 alt+ta ...
- MFC 关于按键状态获取
alt键会阻断消息? moousemovealt键无法判断,按下一次 并松开一次状态改变一次#define KeyState GetAsyncKeyState BOOL bCtrlDown = (Ke ...
- 如何通过minIO在后端实现断点续传
首先是黑马的媒资管理模块流程图:前端负责计算媒资文件的MD5值,同时对媒资文件进行分块. 后端需要以下几个接口: 1.检查分块是否存在(传入参数为视频唯一标识信息与块信息):检查当前分块是否已经上传至 ...
- nacos启动失败:No DataSource set
通过docker查看nacos的日志发现nacos好端端的突然不能用了 docker logs nacos 报错后说是no datasource set,我看了我在docker里的MySQL是正常启动 ...
- 假期小结2hadoop环境配置
记录一下hadoop配置 安装Java Development Kit(JDK):Hadoop是用Java编写的,所以首先需要安装JDK.可以从Oracle下载JDK,并按照安装说明进行安装. 下载 ...
- Fiddler关于https抓包
一.Fiddler默认只抓取HTTP请求 Fiddler安装后默认只抓取HTTP请求,如要抓取HTTPS请求需要进行证书安装 二.Fiddler导出HTTPS证书 1.勾选HTTPS 工具栏Tools ...
- 【HTML】hr标签 分割线 自定义样式
参考: https://blog.csdn.net/weixin_40716682/article/details/90064473 默认是有边框线的 删除边框线,设置高度和背景色即可 backgro ...
- 怎么在Ubuntu系统云服务器搭建自己的幻兽帕鲁服务器?幻兽帕鲁搭建教程
<幻兽帕鲁>是一款备受瞩目的开放世界生存建造游戏,近期在游戏界非常火爆.玩家可以在游戏世界中收集神奇的生物"帕鲁",并利用它们进行战斗.建造.农耕.工业生产等各种活动. ...
- 买二手NVIDIA网卡被坑记录:某宝的咸鱼二手交易网站上购入NVIDIA Mellanox ConnectX-3 网卡 居然不支持Windows 11操作系统 —— 老二手40Gbps的NVIDIA网卡已经不被新操作系统支持
原本是打算去大连的人工智能计算中心去做技术负责人的,不过考虑到工作性质再考虑到自己的一些现实情况也就放弃了这个职位(比较在大连理工大学的博士学位还没有读下来,还是有所牵挂的).同时,由于自己已经退出了 ...
- Jax框架 —— 如何在没有GPU和TPU的设备上debug代码 —— 在CPU上使用GPU仿真设置 —— Jax框架在多卡设备上的自动并行特性的仿真体验
Jax计算框架是Google用来取代Tensorflow的新一代计算框架,这个框架使用类似pytorch的技术,但是在pytorch技术之上加入了更加强大的技术,但是这也导致该框架使用起来要比pyto ...