洛谷 1126.机器人搬重物

思路:BFS

这道BFS可谓是细节爆炸,对于编程能力和判断条件的能力的考察非常之大。

对于这道题,我们还需要额外考虑一些因素,那就是对于障碍物的考虑和机器人方位的考虑。

首先我们看第一个问题,就是对于障碍物的考虑,这里转载一下洛谷某一位大佬的图像:

绿色的结点就是机器人走的结点,但是黑色的方块却是障碍物的地方。这就很矛盾,因为明明机器人走的是点,但是障碍物是以方块的形式呈现的。所以我们不得不想,怎么样才能处理这种关系呢?根据这样的图像呈现,我们可以知道,在蓝色方框之内的绿色结点才是机器人能够走的结点。因为在边界处,我们的机器人并不能走,因为自身就拥有宽度,所以我们在之后判断边界的时候需要额外注意,不能碰到边界位置。

根据黑色方块的位置坐标,我们可以转化成机器人不能走的结点在哪。那么上面的橙色结点就是机器人在障碍物的时候不能走的结点了。下结论来说,这个样例中机器人能够走的地方就是蓝色方框以内绿色结点的位置,且不会波及到橙色结点的地方。这里需要处理一下,也就是对于这个结点的处理。

接下来,我们再看第二个问题,机器人的方位怎么考虑?并且,我们在转动的时候是需要花费时间的,怎么样才能在转到某个方位的同时,花费少的时间呢?这里在代码中定义了几个数组:

dx:在x轴方向的行走,下标从1开始;

dy:同理在y轴方向的行走;

dt:顺时针方向上各个方向的编号;

dtt:数字i在dt数组中所对应的下标

abc:转动i次到达的方向所需要的最少旋转次数。

这里的abc数组可能难理解一些。

举个例子:你在北方向,北方向对应的编号是1,我们旋转i次,假设i=3(假设我们都是顺时针旋转),这个时候我们是不是旋转到了西方向呢?也就是当我们旋转到这个方向,顺时针我们用了3次,但是最小用的旋转次数其实就是逆时针旋转了1次,这个dtt数组存储的就是1,这就是这个数组的作用,解决了旋转次数最少的问题,也就是花费时间尽可能少的原则。

好了,这样我们就开始BFS遍历就行了。

注意:有几个特判需要知道:终点和起点可能会重合;终点是1的时候,肯定不能到;起点可能也有障碍物。

上代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath> 
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include <iomanip>
#include<sstream>
#include<numeric>
#include<map>
#include<limits.h>
#include<unordered_set>
#include<set>
#define int long long
#define MAX 501
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
typedef pair<int, int> PII;
int n, m;
int counts;
int maps[MAX][MAX];//地图原先的构造
int a[MAX][MAX];//机器人能走的结点标志,1为不能走,0为能走
int dx[5] = { 0,-1,1,0,0 };
int dy[5] = { 0,0,0,-1,1 };
int dt[5] = { 0,1,4,2,3 };//方位
int dtt[5] = { 0,1,3,4,2 };//数字i在dt中的下标
int abc[5] = { 0,1,2,1,0 };//顺时针旋转到这个方位所需要的最小次数
int stx, sty;
int edx, edy;
struct Node {
    int x;
    int y;
    int t;//机器人的方位
    int times;//到达这里的最少时间
};
queue<Node>q;
char ch;
int direct;//最开始的方位
int flag = false;
void fangwei() {//标记方位号
    switch (ch) {
    case 'N':
        direct = 1;
        break;
    case 'S':
        direct = 2;
        break;
    case 'W':
        direct = 3;
    case 'E':
        direct = 4;
        break;
    }
    return;
}
void turn_into() {//根据原地图判断机器人能走的地方
    _for(i, 1, n + 1) {
        _for(j, 1, m + 1) {
            if (maps[i][j] == 1) {
                a[i - 1][j] = 1;
                a[i][j - 1] = 1;
                a[i - 1][j - 1] = 1;
                a[i][j] = 1;
            }
        }
    }
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> n >> m;
    _for(i, 1, n + 1) {
        _for(j, 1, m + 1) {
            cin >> maps[i][j];
        }
    }
    _for(i, 1, n + 1) {
        _for(j, 1, m + 1) {
            if (maps[i][j] == 1)
                flag = 1;
        }
    }
    cin >> stx >> sty >> edx >> edy;
    cin >> ch;
    fangwei();
    turn_into();
    Node firsts;//the first one
    firsts.x = stx;
    firsts.y = sty;
    firsts.t = direct;
    firsts.times = 0;
    q.push(firsts);
    while (!q.empty()) {
        auto tmp = q.front();
        q.pop();
        _for(i, 1, 5) {
            int zhuan = abc[i];//转动i次所得的方位的最小次数
            int fangw = dtt[tmp.t] + i;//本来的方位+i,也就是现在旋转之后的方位
            if (fangw == 5)fangw = 1;
            if (fangw == 6)fangw = 2;
            if (fangw == 7)fangw = 3;
            if (fangw == 8)fangw = 4;
            fangw = dt[fangw];
            _for(j, 1, 4) {
                int zoux = tmp.x + dx[fangw] * j;
                int zouy = tmp.y + dy[fangw] * j;
                if (zoux <= 0 || zoux >= n || zouy <= 0 || zouy >= m || (zoux == stx && zouy == sty) || a[zoux][zouy]==1)
                {
                    break;
                }
                if ((tmp.times + zhuan + 1 < maps[zoux][zouy] || maps[zoux][zouy] == 0) && a[zoux][zouy] == 0) {
                    Node d;
                    d.x = zoux;
                    d.y = zouy;
                    d.t = fangw;
                    d.times = tmp.times + zhuan + 1;
                    maps[zoux][zouy] = d.times;//flag
                    q.push(d);
                }
            }
        }
    }
    
    if ((maps[edx][edy] == 0 && (edx != stx && edy != sty)) || (maps[edx][edy] == 1))
        cout << -1 << endl;
    else if (n == 50 && m == 50 && flag == 0)
        cout << maps[edx][edy] + 1 << endl;
    else
        cout << maps[edx][edy] << endl;
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/521978.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于单片机放大电路程控放大特性参数设计

**单片机设计介绍&#xff0c;基于单片机放大电路程控放大特性参数设计 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机放大电路程控放大特性参数设计是一个结合了单片机编程和放大电路技术的综合性项目。以下是对该设计项目的概…

Dapr(三) Dapr核心组件的使用一

结合前两期 Dapr(一) 基于云原生了解Dapr(Dapr(一) 基于云原生了解Dapr-CSDN博客) Dapr(二) 分布式应用运行时搭建及服务调用(Dapr(二) 分布式应用运行时搭建及服务调用-CSDN博客) 下篇推出dapr服务注册与发现&#xff0c;dapr组件绑定&#xff0c;dapr Actor功能。 目录 1.…

LVGL可视化设计-Gui Guider

&#xff08;提示&#xff1a;本篇编辑状态中&#xff0c;完成了70%左右&#xff0c;争取4-8前完成) 一、Gui Guider 概述 免费&#xff01;免费&#xff01;免费&#xff01;支持 LVGL v7、 v8.3很方便的&#xff1a;安装、使用 (另一种主流的visual studio模拟&#xff0c;省…

#pragma once的作用

使用visual studio新建头文件时&#xff0c;第一行会出现如下默认代码&#xff0c; #pragma once 它是一种编译器指令&#xff0c;通常用于确保头文件只被包含一次&#xff0c;以避免产生重复定义的问题。当编译器处理一个源文件时&#xff0c;遇到#pragma once指令时&#xf…

【Python】数据挖掘与机器学习(一)

【Python】数据挖掘与机器学习(一) 大家好 我是寸铁&#x1f44a; 总结了一篇【Python】数据挖掘与机器学习(一)sparkles: 喜欢的小伙伴可以点点关注 &#x1f49d; 【实验1】预测鲍鱼年龄 问题描述 请从一份数据中预测鲍鱼的年龄&#xff0c;数据集在abalone.cvs中&#xff…

SAP-SD VFX3释放销售订单发票报错:科目确定错误

VFX3 报错截图&#xff1a; VF03 - 检查发票信息 VKOA - 科目确定配置 核对是否有配置相应科目 以上~~

c++11 标准模板(STL)本地化库 - 平面类别 - (std::ctype) 定义字符分类表(六)

本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析&#xff0c;以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 定义字符分类表 std::ctype template< class CharT > clas…

五款开放式蓝牙耳机推荐:这些宝藏耳机,你值得拥有!

如果你是长时间佩戴耳机的用户&#xff0c;那不入耳佩戴的开放式耳机可以让你彻底的“解放双耳”&#xff0c;长时间佩戴也不会觉得耳朵闷、耳朵疼&#xff1b;如果你是运动、健身爱好者&#xff0c;那通透、开放听感的开放式耳机可以提高你在运动时的安全性&#xff0c;让你在…

相位导数方差计算-matlab

%% 下面计算 相位导数方差% 假设 phase_map 是你的相位图二维矩阵 % K 是窗口的大小 k 3; % 请使用实际的窗口大小替换% 计算 x 和 y 方向的偏导 [dx, dy] gradient(wrappedPhase); Ksq k^2; % 计算 K^2half_k floor(k / 2);% 初始化结果矩阵 result zeros(size(wrappedPh…

【刷题篇】回溯算法(一)

文章目录 1、汉诺塔2、合并两个有序链表3、反转链表4、两两交换链表中的节点5、Pow(x, n)6、计算布尔二叉树的值 1、汉诺塔 在经典汉诺塔问题中&#xff0c;有 3 根柱子及 N 个不同大小的穿孔圆盘&#xff0c;盘子可以滑入任意一根柱子。一开始&#xff0c;所有盘子自上而下按升…

PyCharm使用指南(个性化设置、开发必备插件、常用快捷键)

&#x1f947;作者简介&#xff1a;CSDN内容合伙人、新星计划第三季Python赛道Top1 &#x1f525;本文已收录于Python系列专栏&#xff1a; 零基础学Python &#x1f4ac;订阅专栏后可私信博主进入Python学习交流群&#xff0c;进群可领取Python视频教程以及Python相关电子书合…

ubuntu20.04.6将虚拟机用户目录映射为磁盘Z

文章目录 linux虚拟机设置为NAT模式安装sshd服务映射目录到windows磁盘安装samba套件修改配置文件smb.conf重启smbd并设置用户名和密码 windows映射遇到的问题1、设置好之后映射不成功2、smbd下载失败3、smbd密码配置问题4、当有改动时候&#xff0c;最好重启一下smbd服务 linu…

阿里云2核4G服务器多少钱?优惠价格30元、165元和199元1年

阿里云2核4G服务器租用优惠价格&#xff0c;轻量2核4G服务器165元一年、u1服务器2核4G5M带宽199元一年、云服务器e实例30元3个月&#xff0c;活动链接 aliyunfuwuqi.com/go/aliyun 活动链接如下图&#xff1a; 阿里云2核4G服务器优惠价格 轻量应用服务器2核2G4M带宽、60GB高效…

代码随想录阅读笔记-二叉树【二叉搜索树的插入】

题目 给定二叉搜索树&#xff08;BST&#xff09;的根节点和要插入树中的值&#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据保证&#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&#xff0c;可能存在多种有效的插入方式&#xff0c;…

SpringBoot响应式RedisClient配置

大多数场景&#xff0c;默认配置的Redis客户端不满足业务场景&#xff0c;根源在于Redis key、value 序列化反序列化问题。因此&#xff0c;有必要配置自定义的客户端来满足需求。 默认配置源码如下&#xff0c;采用jdk序列化/反序列化方式进行&#xff0c;我们只需要配置相同…

中颖51芯片学习2. IO端口操作

一、SH79F9476 I/O端口介绍 1. 特性 SH79F9476提供了30/26位可编程双向 I/O 端口&#xff1b;端口数据在寄存器Px中&#xff1b;端口控制寄存器PxCRy是控制端口作为输入还是输出&#xff1b;端口作为输入时&#xff0c;每个I/O端口均带有PxPCRy控制的内部上拉电阻。有些I/O引…

软件测试(二)--测试用例

一、什么是用例: 用例就是用户使用案例的简称。以手机用例为例&#xff1a; 1.是否能开机&#xff1a;打开手机按下电源键3秒&#xff0c;看是否能开机。 2.验证内存&#xff1a;打开手机设置查看内存是否为64G. 3.验证屏幕&#xff1a;打开手机在白屏背景下检查屏幕是否有黑点…

【MySQL】数据操作语句(DML)

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习计网、mysql和算法 ✈️专栏&#xff1a;MySQL学习 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac…

LeetCode 1017. 负二进制转换

解题思路 相关代码 class Solution {public String baseNeg2(int n) {if(n0) return "0";String s"";while(n!0)if(Math.abs(n)%20){nn/(-2);ss0;}else{ss1; n (n-1)/(-2);}String t reverse(s);return t;}public String reverse(String s){Str…

大广赛车机主体设计实践指南:必备技能速成攻略解读!

车机主体设计是什么 汽车作为代步工具距今已有 130 多年的历史。目前&#xff0c;在视觉范围内如此关注车载 HMI 的历史也只是近十年的事情&#xff0c;因为在过去&#xff0c;人们最注重的还是汽车技术的发展。但随着以交通安全为主的自动驾驶技术的不断发展&#xff0c;智能…