洛谷 P1126 机器人搬重物

news/2025/1/15 15:14:45/

题目描述

机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径 1.6 米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个 N×M 的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:

  • 向前移动 1 步(Creep);
  • 向前移动 2 步(Walk);
  • 向前移动 3 步(Run);
  • 向左转(Left);
  • 向右转(Right)。

每个指令所需要的时间为 1 秒。请你计算一下机器人完成任务所需的最少时间。

输入格式

第一行为两个正整数 N,M (1≤N,M≤50),下面 N 行是储藏室的构造,0 表示无障碍,1 表示有障碍,数字之间用一个空格隔开。接着一行有 4 个整数和 1 个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东 E,南 S,西 W,北 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

这题耗时2个多小时终于算是做出来了

 这题求最少时间,很容易想到用广度搜索,然而这题与一般的找出口最短时间稍微有点不同,

1.需要考虑转变方向所消耗的时间。

2.每次移动不止移动一步。

这里我个人觉得还是要抓住广搜的原理,这题中,广搜是把一秒能发生的运动的所有情况都存下来,这题中,不管是改变方向,还是改变位置,都是一秒发生的,所以都要进行入队操作,我们的标记数组也不单单只标记坐标,还要判断每个坐标的4个方向是否都使用过,多了一个考虑的因素(这里我用三维数组标记),导致题目的难度上升。

这题还有一些需要注意的;

1.因为存在一秒移动多个位置,所以不单单只判断到达的那个点是否是障碍物,还需要判断移动的过程中是否遇到障碍物。

2.终点和起点可能重合(特判就行)

3.机器人占四个格子,只有组成正方形的4个格子都为0才能移动(这里刚开始的时候处理一下就行)

具体操作看代码

AC代码

#include<stdio.h>
struct nb {//结构体列队int x, y;//x为横坐标,y为纵坐标int s, f;//s为步数,//f为方向
}link[850100];
int n, m, x, y, p, q, f;
int hard = 1, tail = 1;
int a[52][52], b[52][52], book[52][52][91];
int main()
{int i, j;scanf("%d %d", &n, &m);//输入矩阵大小for (i = 1; i <= n; i++)for (j = 1; j <= m; j++)scanf("%d", &a[i][j]);for(i=1;i<n;i++)//特殊处理只有4个格子组成的正方形都为0,机器人才能通过for (j = 1; j < m; j++){if (a[i][j] == 0 && a[i][j + 1] == 0 && a[i + 1][j] == 0 && a[i + 1][j + 1] == 0)b[i][j] = 0;elseb[i][j] = 1;}scanf("%d %d %d %d", &x, &y, &p, &q);//输入起点,终点getchar();scanf("%c", &f);//起始朝向if (x == p && y == q)//特判起点终点是否重合{printf("0");return 0;}//起始点入队link[tail].x = x; link[tail].y = y;link[tail].s = 0; if (f == 'E') link[tail].f = 1;//f=1表示东方向,2表示南,3表示西,4表示北else if(f == 'S') link[tail].f = 2;else if (f == 'W') link[tail].f = 3;else  link[tail].f = 4;book[x][y][link[tail].f] = 1; tail++;int flag = 0;//flag用于判断是否找到出口//广搜核心代码while (hard < tail){//先广度搜索方向for (i = 0; i <= 1; i++){int tf;if (i == 0)//0表示左转{tf = link[hard].f + 1;if (tf == 5)tf = 1;}else//右转{tf = link[hard].f - 1;if (tf == 0)tf = 4;}if (book[link[hard].x][link[hard].y][tf] == 0)//如果这个方向没有入队,进行入队操作{link[tail].x = link[hard].x;link[tail].y = link[hard].y;link[tail].s = link[hard].s + 1;link[tail].f = tf;book[link[hard].x][link[hard].y][tf] = 1;tail++;}}//广度搜索不同移动距离for (i = 3; i >= 1; i--){int tx, ty;int fl = 0;//判断移动期间是否遇到障碍物,0为没有遇到if (link[hard].f == 1)//link[hard].f大小不同移动方向不同{tx = link[hard].x;ty = link[hard].y + i;if (tx<1 || tx>n - 1 || ty<1 || ty>m - 1)//是否越界continue;for (j = link[hard].y + 1; j <= ty; j++)//判断是否遇到障碍物{if (b[tx][j] == 1){fl = 1;break;}}}else if (link[hard].f == 2){tx = link[hard].x + i;ty = link[hard].y;if (tx<1 || tx>n - 1 || ty<1 || ty>m - 1)//是否越界continue;for (j = link[hard].x + 1; j <= tx; j++)//判断是否遇到障碍物{if (b[j][ty] == 1){fl = 1;break;}}}else if (link[hard].f == 3){tx = link[hard].x;ty = link[hard].y - i;if (tx<1 || tx>n - 1 || ty<1 || ty>m - 1)//是否越界continue;for (j = link[hard].y - 1; j >= ty; j--)//判断是否遇到障碍物{if (b[tx][j] == 1){fl = 1;break;}}}else{tx = link[hard].x - i;ty = link[hard].y;if (tx<1 || tx>n - 1 || ty<1 || ty>m - 1)//是否越界continue;for (j = link[hard].x - 1; j >= tx; j--)//判断是否遇到障碍物{if (b[j][ty] == 1){fl = 1;break;}}}if (book[tx][ty][link[hard].f] == 0 && fl == 0)//如果这个点的这个方向第一次遇到且到这个点期间没有遇到障碍物{//入队操作+标记link[tail].x = tx;link[tail].y = ty;link[tail].s = link[hard].s + 1;link[tail].f = link[hard].f;book[tx][ty][link[tail].f] = 1;tail++;if (tx == p && ty == q)//如果找到出口标记并提前结束{flag = 1;break;}}}hard++;//一个点广搜完,判断下一个点if (flag == 1)//找到出口,提前结束break;}if (flag == 1)//找到输出最短时间printf("%d", link[tail - 1].s);else//没找到输出-1printf("-1");return 0;
}


http://www.ppmy.cn/news/1329406.html

相关文章

java---多线程-02

线程API sleep阻塞 sleep方法处理异常:InterruptedException. 当一个线程调用sleep方法处于睡眠阻塞的过程中,该线程的interrupt()方法被调用时,sleep方法会抛出该异常从而打断睡眠阻塞. package thread;/*** sleep方法要求必须处理中断异常:InterruptedException* 当一个线程调…

LeetCode.2765. 最长交替子数组

题目 2765. 最长交替子数组 分析 为了得到数组 nums 中的最长交替子数组的长度&#xff0c;需要分别计算以每个下标结尾的最长交替子数组的长度。为了方便处理&#xff0c;计算过程中需要考虑长度等于 1 的最长交替子数组&#xff0c;再返回结果时判断最长交替子数组的长度…

复杂高层建筑环境多模态导航服务和引导管理机器人系统设计(预告)

课题基础 机器人工程ROS方向应用型本科毕业设计重点课题学生验收成果 将上面这篇所涉及的算法等应用到如下环境中。 Gazebo新环境AWS RoboMaker Hospital医院场景适用于ROS1和ROS2 高层可以简化为多层测试。最典型的就是两层及以上。 简介 随着城市化进程的加速和高层建筑…

i18n多国语言Internationalization的动态实现

一、数据动态的更新 在上一篇i18n多国语言Internationalization的实现-CSDN博客&#xff0c;可能会遇到一个问题&#xff0c;我们在进行英文或中文切换时&#xff0c;并没有办法对当前的数据进行动态的更新。指的是什么意思呢&#xff1f;当前app.js当中一个组件内容&#xff…

【算法】用JAVA代码实现LRU 【缓存】【LRU】

LRU(Least Recently Used)是一种常见的缓存淘汰策略,用于在缓存空间不足时确定哪些数据应该被淘汰。其基本原则是淘汰最近最少被访问的数据。 工作原理: 最近使用优先: LRU算法基于这样的思想:最近被使用的数据很可能在短时间内还会被使用,因此保留这些数据有助于提高缓…

【江科大】STM32:TIM输入捕获(理论部分)

文章目录 IC&#xff08;Input Capture&#xff09;输入捕获PWM频率 知识点补充1. 滤波器的工作原理&#xff1a;2. 边沿检测器&#xff1a;自动化清零CNT输入捕获的基本结构PWMI基本结构滤波器和分频器的区别误差分析pwm.cmain.cIC.c PWM模式测频率和占空比 IC&#xff08;Inp…

【K8S in Action】第八章 从应用访问pod元数据

通过环境变量或者configMap和secret卷向应用传递配置数据。这对于pod调度、 运行前预设的数据是可行的。 对于那些不能预先知道的数据&#xff0c; 比如pod的IP、 主机名或者是pod自身的名称。经在别处定义的数据&#xff0c; 比如pod的标签和注解。不想在多个地方重 复保留同样…

C# 获取QQ会话聊天信息

目录 利用UIAutomation获取QQ会话聊天信息 效果 代码 目前遇到一个问题 其他解决办法 利用UIAutomation获取QQ会话聊天信息 效果 代码 AutomationElement window AutomationElement.FromHandle(get.WindowHwnd); AutomationElement QQMsgList window.FindFirst(Tr…