7-54 孤岛营救问题——状压bfs+三维标记

news2024/11/28 0:55:52

1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图。迷宫的外形是一个长方形,
其南北方向被划分为 n 行,东西方向被划分为 m 列,于是整个迷宫被划分为 n×m 个单元。每一个单元的位置可用一个有序数对 (单元的行号, 单元的列号) 来表示。南北或东西方向相邻的 2 个单元之间可能互通,也可能有一扇锁着的门,或者是一堵不可逾越的墙。迷宫中有一些单元存放着钥匙,并且所有的门被分成 p 类, 打开同一类的门的钥匙相同,不同类门的钥匙不同。

大兵瑞恩被关押在迷宫的东南角,即 (n,m) 单元里,并已经昏迷。迷宫只有一个入口, 在西北角。也就是说,麦克可以直接进入 (1,1) 单元。另外,麦克从一个单元移动到另一个 相邻单元的时间为 1,拿取所在单元的钥匙的时间以及用钥匙开门的时间可忽略不计。

试设计一个算法,帮助麦克以最快的方式到达瑞恩所在单元,营救大兵瑞恩。

在这里插入图片描述

输入样例:
在这里给出一组输入。例如:

4 4 9
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2
4 2 1
输出样例:
在这里给出相应的输出。例如:

14

分析

  1. 之前dfs写了这个没过,后来忘了写了现在想起来这个题了,补一个题;首先此题和T1215 拯救公主——bfs+三维数组标记+二进制状态压缩有点像,这题就是到达一个点,可能有门,需要你有钥匙,钥匙有很多种类,然后拥有不同钥匙状态在同一点的状态也不一样,那这就是状压bfs;状态k的二进制00001就表示有第1种门的钥匙,状态为10000表示有第5种门的钥匙;
  2. 用状压,就少不了位运算,一些位运算的操作含义1<<2 表示把左边的操作数1(0001)左移2位,那就是1*2^2=4(0001=》0100);| 就是二进制序列进行或运算;|= 就是二进制序列进行或运算,把运算结果赋值给左边;
  3. 1<<(x-1)是下面代码常见的操作,就是把操作数1的二进制序列的1向左移(x-1)位;
  4. bfs的逻辑就是,先判断是否越界、是否有墙挡着;然后判断,到达的点是否是门,是门的话(g[x][y][xx][yy]>0),看看当前的钥匙状态k,是否有这个门所需要的,k & 1 << (g[x][y][xx][yy] - 1),看看当前的钥匙状态 & 这个门所需要的钥匙状态,不为0就说明有这个门的钥匙;然后更新当前新状态kk(k | getKeyStatus(xx, yy)),在这个点(xx,yy)没访问过就加入队列;
  5. 此题的坑点:就是一个地方(x,y),可能有多把钥匙,所以三维key,存储是该点有几种钥匙;而且碰见这种输入的是两个点连通情况的,n比较小的话,直接四维数组存图;
#include<bits/stdc++.h>

using namespace std;

struct node {
    int x, y, step, k;//k:当前钥匙的拥有状态
    node(int xx, int yy, int stp, int kk) {
        x = xx, y = yy, step = stp, k = kk;
    }
};

int n, m, p, k, s, ans = 100;
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
int g[15][15][15][15];
int vis[15][15][1 << 15];//第三维是钥匙的状压
int keyCnt[15][15];//每个位置的钥匙数
int key[15][15][15];//第三维就是该点有几种钥匙
queue<node> q;

//获取(x,y)的钥匙状态
int getKeyStatus(int x, int y) {
    int ret = 0;
    for (int i = 1; i <= keyCnt[x][y]; ++i) {
        //  |= 去组合这几种钥匙的合体状态(ret也就是拥有keyCnt[x][y]种钥匙的二进制序列的十进制数)
        //  1<<1  《==》 1*(2^1) :1往左移的位数  比如第i把钥匙为1,那么二进制序列就是0001,就是 1 << (1-1)
        ret |= (1 << (key[x][y][i] - 1));//1 << (key[x][y][i] - 1)表示当前这把钥匙类型的二进制的状态
    }
    return ret;
}

void bfs() {
    vis[1][1][getKeyStatus(1, 1)] = 1;
    q.push(node(1, 1, getKeyStatus(1, 1), 0));
    while (!q.empty()) {
        node current = q.front();
        int x = current.x, y = current.y, step = current.step, k = current.k;
        q.pop();
        //到达终点
        if (x == n && y == m) {
            ans = step;
            return;
        }
        for (int i = 0; i < 4; ++i) {
            int xx = x + dx[i];
            int yy = y + dy[i];
            //不越界+有路
            if (xx >= 1 && yy >= 1 && xx <= n && yy <= m && g[x][y][xx][yy] >= 0) {
                //如果要到达的点有门,判断是否有这个门钥匙,看看当前的钥匙状态 & 这个门所需要的钥匙状态,不为0就说明有
                if (g[x][y][xx][yy] && !(k & 1 << (g[x][y][xx][yy] - 1)))
                    continue;
                //更新走到(xx,yy)的钥匙状态,因为(xx,yy)可能也有钥匙
                int kk = k | getKeyStatus(xx, yy);//  |运算一下,来把新钥匙加入原来的钥匙状态k,组成新的状态kk
                if (!vis[xx][yy][kk]) {
                    q.push(node(xx, yy, step + 1, kk));
                    vis[xx][yy][kk] = 1;
                }

            }
        }
    }
}

int main() {
    cin >> n >> m >> p >> k;
    int a, b, c, d, e;
    for (int i = 1; i <= k; ++i) {
        cin >> a >> b >> c >> d >> e;
        //无向图
        if (e == 0)// 用-1表示墙
            g[a][b][c][d] = g[c][d][a][b] = -1;
        else
            g[a][b][c][d] = g[c][d][a][b] = e;
    }
    cin >> s;
    for (int i = 1; i <= s; ++i) {
        cin >> a >> b >> c;
        //(a,b)点的第keyCnt[a][b]的钥匙是c
        key[a][b][++keyCnt[a][b]] = c;
    }
    bfs();
    if (ans == 100)
        cout << -1;
    else
        cout << ans;
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二、小程序框架

目录 框架 一、响应的数据绑定 二、页面管理 三、基础组件 四、丰富的API 模块化 一、模块化 二、文件作用域 三、API 视图层 View 一、WXML 事件 什么是事件 事件的使用方式 使用 WXS 函数响应事件 事件详解 框架 小程序开发框架的目标是通过尽可能简单、高效…

万字长文详解 YOLOv1-v5 系列模型

一&#xff0c;YOLOv1二&#xff0c;YOLOv2三&#xff0c;YOLOv3四&#xff0c;YOLOv4五&#xff0c;YOLOv5参考资料 一&#xff0c;YOLOv1 YOLOv1 出自 2016 CVPR 论文 You Only Look Once:Unified, Real-Time Object Detection. YOLO 系列算法的核心思想是将输入的图像经过…

同时安装python3和Python2

一刚开始我很疑惑&#xff0c;Python为何要并行两个版本呢&#xff1f;今天我算知道了&#xff0c;原来是因为有的项目一直在用python2。虽然我已经安装了python3但是那些使用python2进行部署的项目我仍然无法使用&#xff0c;这就导致我要在电脑上同时安装python2和Python3了。…

【无标题】SIP网络广播音频模块

SIP2101V和SIP2103V网络音频模块是一款通用的独立SIP音频功能模块&#xff0c;可以轻松地嵌入到OEM产品中。该模块对来自网络的SIP协议及RTP音频流进行编解码。 该模块支持多种网络协议和音频编解码协议&#xff0c;可用于VoIP和IP寻呼以及高质量音乐流媒体播放等应用。同时&a…

如何将onnx转ncnn供移动端推理使用

ncnn是一个为手机端极致优化的高性能神经网络前向计算框架。基于 ncnn&#xff0c;开发者能够将深度学习算法轻松移植到手机端高效执行&#xff0c;开发出人工智能 APP&#xff0c;将 AI 带到你的指尖。 但是onnx直接转ncnn会存在很多问题&#xff0c;所以一般考虑都是先将onn…

Mysql 进阶(面向面试篇)InnoDB引擎(redo log undolog readview mvcc)

1.1 逻辑存储结构 1). 表空间 表空间是InnoDB存储引擎逻辑结构的最高层&#xff0c; 如果用户启用了参数 innodb_file_per_table(在8.0版本中默认开启) &#xff0c;则每张表都会有一个表空间&#xff08;xxx.ibd&#xff09;&#xff0c;一个mysql实例可以对应多个表空间&…

【ElasticSearch 进阶】倒排索引 + FOR + RBM压缩算法

1. 倒排索引 如果有100w的数据&#xff0c;进行分词后&#xff0c;每个id按数字类型进行存储&#xff0c;假设每个行数据都包含相同的词&#xff0c;则每个词的 Posting List 需要占用约4M的空间&#xff1a; 1 int 4 Bytes 100W int 400W Bytes ≈ 4M 极大的浪费了空间。则需…

IDC:中国网络安全市场投资规模将在2026年达到319亿美元

近日&#xff0c;IDC咨询发布《IDC Market Forecast&#xff1a;中国网络安全市场预测&#xff0c;2022-2026》报告&#xff0c;对未来五年的中国网络安全市场发展走向做出分析预测。报告认为&#xff0c;中国IT安全市场投资规模逐年攀升&#xff0c;到2026年将达到319亿美元&a…

MySQL经典50题

MySQL经典50题 mysq经典50题拿来练手 文章目录MySQL经典50题创建表及信息录入1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数3、查询平均成绩大于等于60分的同学的学生…

[阶段4 企业开发进阶] 5. Netty

文章目录1 Netty1.1 Netty介绍1.2 Netty应用场景2 Java BIO编程2.1 IO模型2.2 BIO、NIO、AIO 适用场景分析2.3 BIO3 Java NIO编程3.1 NIO基本介绍3.2 NIO和BIO的比较3.3 NIO三大核心原理1 Netty 1.1 Netty介绍 Netty 是由 JBOSS 提供的一个 Java 开源框架Netty 是一个异步的、…

技术分享 | 做为测试,那些必须掌握的测试技术体系

软件测试技术是软件开发过程中的一个重要组成部分&#xff0c;是贯穿整个软件开发生命周期、对软件产品&#xff08;包括阶段性产品&#xff09;进行验证和确认的活动过程。其目的是尽快尽早地发现在软件产品中所存在的各种问题&#xff0c;与用户需求、预先定义的不一致性。检…

Revit 中柱子附着屋顶小技巧和“柱断墙梁”方法

一、Revit 中柱子附着屋顶小技巧 Revit 中如何正确的使柱子附着于屋顶? 有的朋友绘制完结构柱后想要附着到屋顶上&#xff0c;这时候大家会选择把柱子顶部拉上去或者选择“附着顶部/底部”命令。但是这样会出现如图 1所示情况 此时柱子并未与屋顶完全相交&#xff0c;这时候有…

seata分布式事务AT模式原理解析

文章目录TC相关的表解析AT 模式如何做到对业务的无侵入写隔离读隔离AT模式特点TC相关的表解析 global_table&#xff1a;全局事务表&#xff0c;每当有一个全局事务发起后&#xff0c;就会在该表中记录全局事务的ID。branch_table&#xff1a;分支事务表&#xff0c;记录每一个…

一个简单实用的 JavaScript 日历控件源代码,不依赖第三方库,支持日期、月份、年份视图切换;支持单选、多选、范围和星期选

一个简单实用的 JavaScript 日历控件&#xff01;原生 JavaScript 编写&#xff0c;不依赖任何第三方库。支持日期、月份和年份试图切换&#xff1b;支持单选、多选、范围和星期选择模式&#xff1b;界面简介、配置简单、使用方便&#xff01; 完整代码下载地址&#xff1a;一个…

java计算机毕业设计ssm招聘信息管理平台9kvyw(附源码、数据库)

java计算机毕业设计ssm招聘信息管理平台9kvyw&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff0…

终于有P8大佬把困扰我多年的《计算机网络原理》全部讲明白了

前言 为什么网络协议这么重要呢&#xff1f;集群规模一大&#xff0c;我们首先想到的就是网络互通的问题&#xff1b;应用吞吐量压不上去&#xff0c;我们首先想到的也是网络互通的问题。所以&#xff0c;要成为技术牛人&#xff0c;搞定大系统&#xff0c;一定要过网络这一关&…

投影仪可以当电视看吗?告诉你好用的电视应用市场,建议收藏

当初在买投影仪和买电视中纠结了很久&#xff0c;最终选择了投影仪&#xff0c;现在又想看电视了……但是又不想再买个电视&#xff0c;那么问题来了&#xff0c;投影仪可以当电视用吗&#xff1f;经过本人一番研究&#xff0c;终于找到投影仪看电视的最简单方法&#xff1a;安…

Go C 编程 第3课 魔法自动机

慧通教育 慧通教育 30.画奔驰车标志(魔法学院第3课) 难度&#xff1a;1 登录 31.画拱型(魔法学院第3课) 难度&#xff1a;1 登录 32.画正三角形(魔法学院第3课) 难度&#xff1a;1 登录 33.画棱形(魔法学院第3课) 难度&#xff1a;1 登录 魔法学院的奇幻之旅&#xff1a;…

「安全狗漏洞通告」Fortinet SSL VPN远程代码执行漏洞解决方案

安全狗应急响应中心监测到&#xff0c;Fortinet发布了FortiOS SSL-VPN的风险通告&#xff0c;漏洞等级&#xff1a;高危&#xff0c;漏洞评分&#xff1a;9.3。漏洞编号&#xff1a;CVE-2022-42475。 安全狗应急响应中心建议广大用户做好资产自查以及预防工作&#xff0c;以免遭…

理解DDR Part 1

DDR x4 x8 x16 x4 x8 x16 指的上图黑色的chip输出的位宽&#xff0c;正常的DDR bus width 需要64bit&#xff0c;所以 chip width x4 x8 x16 黑色chip数量 16 8 4 上图是最常见的x8&#xff0c;也就有8个黑色的chip颗粒。x16的性能和x8的性能相比怎么样呢? 更差&…