华为OD机试真题 - 特殊的加密算法 - 深度优先搜索DFS(Python/JS/C/C++ 2024 D卷 200分)

news2024/9/23 7:34:11

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

有一种特殊的加密算法,明文为一段数字串,经过密码本查找转换,生成另一段密文数字串。

规则如下

  1. 明文为一段数字串由0-9组成
  2. 密码本为数字0-9组成的二维数组
  3. 需要按明文串的数字顺序在密码本里找到同样的数字串,密码本里的数字串是由相邻的单元格数字组成,上下和左右是相邻的,注意:对角线不相邻,同一个单元格的数字不能重复使用。
  4. 每一位明文对应密文即为密码本中找到的单元格所在的行和列序号(序号从0开始)组成的两个数字。如明文第位Data[i]对应密码本单元格为Book[x][y],则明文第i位对应的密文为XY,X和Y之间用空格隔开

如果有多条密文,返回字符序最小的密文。如果密码本无法匹配,返回"error"

二、输入描述

第一行输入1个正整数N,代表明文的长度(1<= N <= 200)

第二行输入N个明文数字组成的序列Data[i] (整数: 0<= Data[i]<= 9)

第三行1个正整数M,代表密文的长度接下来M行,每行M个数,代表密文矩阵

三、输出描述

输出字典序最小密文.如果无法匹配,输出"error

四、测试用例

测试用例1:

1、输入

2
0 3
3
0 0 2
1 3 4
6 6 4

2、输出

0 1 1 1

3、说明

目标是找到密码本中所有与明文匹配的路径,并输出字典序最小的路径。

  1. 从位置 (0, 0) 开始:
    • 当前单元格值是 0,匹配明文的第一个数字 0。
    • 接下来在相邻单元格中寻找 3,可选的相邻单元格有:
    • (0, 1) -> 值是 0
    • (1, 0) -> 值是 1
    • 没有找到匹配的数字 3,继续搜索下一个起点。
  2. 从位置 (0, 1) 开始:
    • 当前单元格值是 0,匹配明文的第一个数字 0。
    • 接下来在相邻单元格中寻找 3,可选的相邻单元格有:
    • (0, 0) -> 值是 0
    • (0, 2) -> 值是 2
    • (1, 1) -> 值是 3(匹配!)
    • 路径为:(0, 1) -> (1, 1),对应的密文为 0 1 1 1。
  3. 从其他起点继续搜索(如(0, 2), (1, 0), 等),但这些都不能找到有效的路径。

在所有可能的路径中,唯一找到的路径是从 (0, 1) -> (1, 1),对应的密文为 0 1 1 1。

测试用例2:

1、输入

2
0 5
3
0 0 2
1 3 4
6 6 4

2、输出

error

3、说明

  1. 从位置 (0, 0) 开始:
    • 当前单元格值是 0,匹配明文的第一个数字 0。
    • 接下来在相邻单元格中寻找 5,可选的相邻单元格有:
    • (0, 1) -> 值是 0
    • (1, 0) -> 值是 1
    • 没有找到匹配的数字 5,继续搜索下一个起点。
  2. 从位置 (0, 1) 开始:
    • 当前单元格值是 0,匹配明文的第一个数字 0。
    • 接下来在相邻单元格中寻找 5,可选的相邻单元格有:
    • (0, 0) -> 值是 0
    • (0, 2) -> 值是 2
    • (1, 1) -> 值是 3
    • 没有找到匹配的数字 5,继续搜索下一个起点。
  3. 从其他起点继续搜索(如(0, 2), (1, 0), 等),但这些都不能找到有效的路径。

在密码本中,数字 5 并不存在,因此没有找到任何匹配路径。

五、解题思路

1、深度优先搜索DFS

DFS (Depth-First Search) 是一种用于遍历或搜索树或图的算法。它从一个起点出发,尽可能深入探索每一个分支,直到不能再深入为止,然后回溯到上一个节点继续探索其他分支。

在本题中,DFS 用于在密码本矩阵中查找与明文数字序列匹配的路径。每找到一个符合条件的单元格,继续递归搜索其相邻单元格,直到找到完整的明文序列或搜索失败。

2、为什么采用深度优先搜索DFS?

采用深度优先搜索(DFS)算法有以下几个原因:

DFS 是一种遍历或搜索图或树数据结构的算法,特别适用于路径搜索问题。因为它会从一个起点出发,尽可能深入到某个分支的尽头,然后回溯,探索其他未访问的分支。在本题中,我们需要在二维矩阵中找到一条特定的路径,DFS 是一种合适的选择。

在本题中,密码本的大小是有限的(最大 200x200),这使得 DFS 在时间和空间复杂度上是可接受的。DFS 的时间复杂度是 O(V + E),其中 V 是节点数,E 是边数。对于矩阵搜索问题,节点数和边数都是有限的,因此 DFS 是有效的。

3、具体步骤:

  1. 读取输入:从标准输入中读取明文长度、明文数字序列、密码本矩阵的大小和内容。
  2. 初始化数据结构:准备用于深度优先搜索(DFS)的辅助数据结构,包括密码本矩阵、访问记录矩阵和用于构建路径的字符串生成器。
  3. 遍历起点:从密码本矩阵中的每一个可能的起点开始,尝试匹配明文数字序列。
  4. 深度优先搜索(DFS):递归搜索从当前起点出发的所有可能路径:
    • 检查当前单元格是否与明文的当前数字匹配。
    • 如果匹配,继续搜索其相邻单元格(上下左右四个方向)。
    • 在每一步搜索中,记录路径并标记已访问单元格,避免重复使用。
    • 如果找到一条完整的路径,与当前已找到的最优路径比较,更新最优路径。
  5. 输出结果:遍历完所有可能的起点后,输出字典序最小的路径,如果没有找到匹配路径,输出 “error”。

六、Python算法源码

def dfs(book, data, visited, x, y, index, M, path, N):
    global minPath
    # 如果已经匹配到明文的最后一个数字
    if index == N - 1:
        current_path = " ".join(map(str, path))
        # 更新字典序最小的路径
        if minPath is None or current_path < minPath:
            minPath = current_path
        return

    # 定义方向数组,用于表示上下左右四个方向
    dx = [-1, 1, 0, 0]
    dy = [0, 0, -1, 1]

    # 遍历四个方向
    for i in range(4):
        new_x = x + dx[i]
        new_y = y + dy[i]
        # 检查新的位置是否在矩阵范围内,是否未访问过,且与明文的下一个数字匹配
        if 0 <= new_x < M and 0 <= new_y < M and not visited[new_x][new_y] and book[new_x][new_y] == data[index + 1]:
            visited[new_x][new_y] = True  # 标记新的位置为访问过
            path.append((new_x, new_y))   # 更新路径
            # 继续深度优先搜索
            dfs(book, data, visited, new_x, new_y, index + 1, M, path, N)
            path.pop()                    # 回溯,移除最后添加的路径
            visited[new_x][new_y] = False  # 取消访问标记

def main():
    global minPath
    minPath = None

    # 读取输入
    N = int(input())
    data = list(map(int, input().split()))

    M = int(input())
    book = [list(map(int, input().split())) for _ in range(M)]

    # 尝试从每一个位置开始搜索
    for i in range(M):
        for j in range(M):
            # 如果当前单元格的值与明文的第一个数字匹配
            if book[i][j] == data[0]:
                visited = [[False] * M for _ in range(M)]  # 记录访问过的单元格
                visited[i][j] = True  # 标记当前单元格为访问过
                # 从当前位置开始深度优先搜索
                dfs(book, data, visited, i, j, 0, M, [(i, j)], N)

    # 输出结果
    print(minPath if minPath is not None else "error")

if __name__ == "__main__":
    main()

七、JavaScript算法源码

let dx = [-1, 1, 0, 0];
let dy = [0, 0, -1, 1];
let minPath = null; // 存储字典序最小的路径

function dfs(book, data, visited, x, y, index, M, path, N) {
    // 如果已经匹配到明文的最后一个数字
    if (index === N - 1) {
        let currentPath = path.join(" ");
        // 更新字典序最小的路径
        if (minPath === null || currentPath < minPath) {
            minPath = currentPath;
        }
        return;
    }

    // 遍历四个方向
    for (let i = 0; i < 4; i++) {
        let newX = x + dx[i];
        let newY = y + dy[i];
        // 检查新的位置是否在矩阵范围内,是否未访问过,且与明文的下一个数字匹配
        if (newX >= 0 && newX < M && newY >= 0 && newY < M && !visited[newX][newY] && book[newX][newY] === data[index + 1]) {
            visited[newX][newY] = true;  // 标记新的位置为访问过
            path.push(newX + " " + newY);  // 更新路径
            // 继续深度优先搜索
            dfs(book, data, visited, newX, newY, index + 1, M, path, N);
            path.pop();  // 回溯,移除最后添加的路径
            visited[newX][newY] = false;  // 取消访问标记
        }
    }
}

function main() {
    const input = prompt("请输入数据:").split("\n");
    let inputIndex = 0;

    // 读取明文长度
    const N = parseInt(input[inputIndex++]);

    // 读取明文数字序列
    const data = input[inputIndex++].split(" ").map(Number);

    // 读取密码本的大小
    const M = parseInt(input[inputIndex++]);

    // 读取密码本矩阵
    let book = [];
    for (let i = 0; i < M; i++) {
        book.push(input[inputIndex++].split(" ").map(Number));
    }

    // 尝试从每一个位置开始搜索
    for (let i = 0; i < M; i++) {
        for (let j = 0; j < M; j++) {
            // 如果当前单元格的值与明文的第一个数字匹配
            if (book[i][j] === data[0]) {
                let visited = Array.from({ length: M }, () => Array(M).fill(false));  // 记录访问过的单元格
                visited[i][j] = true;  // 标记当前单元格为访问过
                // 从当前位置开始深度优先搜索
                dfs(book, data, visited, i, j, 0, M, [`${i} ${j}`], N);
            }
        }
    }

    // 输出结果
    console.log(minPath === null ? "error" : minPath);
}

// 调用主函数
main();

八、C算法源码

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#define MAX_M 100
#define MAX_PATH_LEN 1000

int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
char minPath[MAX_PATH_LEN];  // 存储字典序最小的路径

void dfs(int book[MAX_M][MAX_M], int data[], bool visited[MAX_M][MAX_M], int x, int y, int index, int M, char path[], int N) {
    // 如果已经匹配到明文的最后一个数字
    if (index == N - 1) {
        if (strlen(minPath) == 0 || strcmp(path, minPath) < 0) {
            strcpy(minPath, path);
        }
        return;
    }

    // 遍历四个方向
    for (int i = 0; i < 4; i++) {
        int newX = x + dx[i];
        int newY = y + dy[i];
        // 检查新的位置是否在矩阵范围内,是否未访问过,且与明文的下一个数字匹配
        if (newX >= 0 && newX < M && newY >= 0 && newY < M && !visited[newX][newY] && book[newX][newY] == data[index + 1]) {
            visited[newX][newY] = true;  // 标记新的位置为访问过
            char newPath[MAX_PATH_LEN];
            sprintf(newPath, "%s %d %d", path, newX, newY);  // 更新路径
            // 继续深度优先搜索
            dfs(book, data, visited, newX, newY, index + 1, M, newPath, N);
            visited[newX][newY] = false;  // 取消访问标记
        }
    }
}

int main() {
    int N, M;
    int data[MAX_M];
    int book[MAX_M][MAX_M];
    bool visited[MAX_M][MAX_M] = { false };  // 访问记录矩阵

    // 初始化 minPath
    memset(minPath, 0, sizeof(minPath));

    // 读取明文长度
    scanf("%d", &N);

    // 读取明文数字序列
    for (int i = 0; i < N; i++) {
        scanf("%d", &data[i]);
    }

    // 读取密码本的大小
    scanf("%d", &M);

    // 读取密码本矩阵
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < M; j++) {
            scanf("%d", &book[i][j]);
        }
    }

    // 尝试从每一个位置开始搜索
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < M; j++) {
            // 如果当前单元格的值与明文的第一个数字匹配
            if (book[i][j] == data[0]) {
                visited[i][j] = true;  // 标记当前单元格为访问过
                char startPath[MAX_PATH_LEN];
                sprintf(startPath, "%d %d", i, j);
                // 从当前位置开始深度优先搜索
                dfs(book, data, visited, i, j, 0, M, startPath, N);
                visited[i][j] = false;  // 取消访问标记
            }
        }
    }

    // 输出结果
    if (strlen(minPath) == 0) {
        printf("error\n");
    } else {
        printf("%s\n", minPath);
    }

    return 0;
}

九、C++算法源码

#include <iostream>
#include <vector>
#include <string>
#include <climits>

using namespace std;

vector<int> dx = {-1, 1, 0, 0};
vector<int> dy = {0, 0, -1, 1};
string minPath;  // 存储字典序最小的路径

void dfs(const vector<vector<int>>& book, const vector<int>& data, vector<vector<bool>>& visited, int x, int y, int index, int M, string path, int N) {
    // 如果已经匹配到明文的最后一个数字
    if (index == N - 1) {
        if (minPath.empty() || path < minPath) {
            minPath = path;
        }
        return;
    }

    // 遍历四个方向
    for (int i = 0; i < 4; i++) {
        int newX = x + dx[i];
        int newY = y + dy[i];
        // 检查新的位置是否在矩阵范围内,是否未访问过,且与明文的下一个数字匹配
        if (newX >= 0 && newX < M && newY >= 0 && newY < M && !visited[newX][newY] && book[newX][newY] == data[index + 1]) {
            visited[newX][newY] = true;  // 标记新的位置为访问过
            dfs(book, data, visited, newX, newY, index + 1, M, path + " " + to_string(newX) + " " + to_string(newY), N);
            visited[newX][newY] = false;  // 取消访问标记
        }
    }
}

int main() {
    int N, M;
    cin >> N;

    vector<int> data(N);
    for (int i = 0; i < N; i++) {
        cin >> data[i];
    }

    cin >> M;
    vector<vector<int>> book(M, vector<int>(M));
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < M; j++) {
            cin >> book[i][j];
        }
    }

    minPath = "";

    // 尝试从每一个位置开始搜索
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < M; j++) {
            // 如果当前单元格的值与明文的第一个数字匹配
            if (book[i][j] == data[0]) {
                vector<vector<bool>> visited(M, vector<bool>(M, false));  // 记录访问过的单元格
                visited[i][j] = true;  // 标记当前单元格为访问过
                dfs(book, data, visited, i, j, 0, M, to_string(i) + " " + to_string(j), N);
            }
        }
    }

    // 输出结果
    if (minPath.empty()) {
        cout << "error" << endl;
    } else {
        cout << minPath << endl;
    }

    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

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

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

相关文章

C++:priority_queue(优先级队列)的模拟实现

目录 一、什么是优先级队列 二、优先级队列的定义 三、优先级队列的常用接口 四、模拟实现一个优先级队列 1、posh接口 2、empty接口、size接口和top接口 3、pop接口 4、构造函数 五、整体代码 一、什么是优先级队列 首先优先级队列不是队列&#xff0c;C 中的优先队…

IP包头的总长度字段和UDP包头的长度字段之间的关系

IP包头的总长度字段和UDP包头的长度字段之间的关系&#xff0c;并通过实例加以说明。 IP包头的总长度字段 **总长度&#xff08;Total Length&#xff09;**字段是一个16位的字段&#xff0c;表示整个IP数据包的总长度&#xff0c;包括IP包头和数据部分。单位是字节。由于该字…

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人&#xff0c;是不是经常需要制作各种PPT来分享我的生活和想法。但是&#xff0c;你们知道&#xff0c;有时候灵感来了&#xff0c;时间却不够用了&#xff01;&#x1f629;直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手&#…

PID控制算法(二)

&#xff08;BIlibili借鉴&#xff09;PID参数整定连接&#xff1a;Webpack App (rossning92.github.io) C的基本程序代码&#xff1a; 借鉴链接&#xff1a;PID超详细教程——PID原理串级PIDC代码在线仿真调参-CSDN博客 #include <iostream>using namespace std;stru…

【信创】统信UOS桌面UT-2024-0027漏洞修复

原文链接&#xff1a;【信创】统信UOS系统UT-2024-0027漏洞修复 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于统信UOS桌面操作系统UT-2024-0027漏洞修复的文章。漏洞修复是确保系统安全性的重要步骤&#xff0c;及时更新和修复系统中的安全漏洞&#xff0c;可…

大数据之Flink(三)

9.3、转换算子 9.3.1、基本转换算子 9.3.1.1、映射map 一一映射 package transform;import bean.WaterSensor; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; impor…

Go开源日志库Logrus的使用

一、Logrus简介 Logrus 是一个流行的 Go 语言日志库&#xff0c;以其功能强大、性能高效和高度灵活性而闻名。有关更多介绍可查看 Logrus。 主要特点 丰富的日志级别&#xff1a;Logrus 支持多种日志级别&#xff0c;包括 Debug、Info、Warn、Error、Fatal 和 Panic&#xf…

深入理解数据库的 4NF:多值依赖与消除数据异常

在数据库设计中&#xff0c; "范式" 是一个常常被提到的重要概念。许多初学者在学习数据库设计时&#xff0c;经常听到第一范式&#xff08;1NF&#xff09;、第二范式&#xff08;2NF&#xff09;、第三范式&#xff08;3NF&#xff09;以及 BCNF&#xff08;Boyce-…

RESTful 还是 JSON-RPC

前言 RESTful 比较简单地说就是&#xff0c;大家请求一样的url&#xff08;GET方法有一个例外&#xff0c;url中带了一个id&#xff09;&#xff0c;通过不同的请求方法&#xff0c;分别进行不同的操作&#xff08;CRUD&#xff09;。 JSON-RPC JSON-RPC是一个无状态且轻量级…

SpringBoot学习(7)(Bean对象注册)(自定义组合注解)

目录 一、引言 二、案例学习 &#xff08;一&#xff09;Bean &#xff08;二&#xff09;Import 三、补充 &#xff08;1&#xff09;关于Java中collection.toArray(new String[0])解释 &#xff08;2&#xff09;组合注解 一、引言 上次学习了解到&#xff0c;springb…

基于机器学习的阿尔兹海默症智能分析预测系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 阿尔兹海默症&#xff08;Alzheimers Disease, AD&#xff09;是一种常见的神经退行性疾病&#xff0c;主要影响老年人的认知功能。随着全球人口老龄化的加剧&#xff0c;阿尔兹海默症的患病率逐年…

nodejs 使用kafka案例,node-red配置kafka案例,从安装配置kafka开始

生产者测试&#xff1a; bin/kafka-console-producer.sh --broker-list 1.2.3.4:9092 --topic test-topic消费者测试&#xff1a; bin/kafka-console-consumer.sh --bootstrap-server 1.2.3.4:9092 --topic test-topic --from-beginningconst { Kafka } require(kafkajs)con…

【AIGC数字人】EchoMimic:基于可编辑关键点条件的类人音频驱动肖像动画

GitHub&#xff1a;https://github.com/BadToBest/EchoMimic 论文&#xff1a; https://arxiv.org/pdf/2407.08136 comfyui&#xff1a; https://github.com/smthemex/ComfyUI_EchoMimic 相关工作 Wav2Lip Wav2Lip是一个开创性的工作 &#xff0c;但输出会出现面部模糊或扭…

粒子群算法原理的示例介绍

一&#xff1a;粒子群优化算法的介绍 粒子群优化算法&#xff08;PSO&#xff09;是一种基于群体智能的优化算法&#xff0c;于1995年提出。它受到鸟群狩猎行为的启发&#xff0c;通过模拟鸟群或鱼群的社会行为来进行问题的求解。 基本原理 粒子群算法中&#xff0c;每个解决…

顶刊算法 | Matlab实现鹈鹕算法POA-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测,优化前后对比

顶刊算法 | Matlab实现鹈鹕算法POA-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测&#xff0c;优化前后对比 目录 顶刊算法 | Matlab实现鹈鹕算法POA-CNN-LSTM-Multihead-Attention多头注意力机制多变量时间序列预测&#xff0c;优化前后对比预测效果基本介绍…

一种小众且适合发文的智能优化算法应用——三维TSP问题

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 今天给大家介绍一种非常小众的智能优化算法应用&am…

【LabVIEW学习篇 - 21】:DLL与API的调用

文章目录 DLL与API调用DLLAPIDLL的调用 DLL与API调用 LabVIEW虽然已经足够强大&#xff0c;但不同的语言在不同领域都有着自己的优势&#xff0c;为了强强联合&#xff0c;LabVIEW提供了强大的外部程序接口能力&#xff0c;包括DLL、CIN(C语言接口)、ActiveX、.NET、MATLAB等等…

2024/9/9 408“回头看”:

B树是什么&#xff1f;有什么作用&#xff1f;B树的插入和删除具体细节是什么&#xff1f;除了B树还有一个是B&#xff0b;树、还是B-树&#xff0c;他们有什么区别&#xff0c;又有什么相同点&#xff1f; b树在王道考研查找这一章&#xff0c;所以他的主要作用就是查找。 在…

MySQL中binary放在判断语句之前有什么作用

为什么要加binary进行判断 ① 因为 mysql中等号比较是不区分大小写的&#xff0c;select aA这个输出结果为1。 ② 在判断语句之前 加上binary可以以区分大小写比较 &#xff0c;因为这样底层会用二进制形式比较&#xff0c;实现精确匹配。 代码比较 忽略大小写比较 select …

Ftrans跨域文件传输方案,数据流动无阻的高效路径

大型集团企业由于其规模庞大、业务广泛且往往将分支机构、办事处分布在多个地域&#xff0c;因此会涉及到跨域文件传输的需求。主要源于以下几个方面&#xff1a; 1.业务协同&#xff1a;集团内部的不同部门或子公司可能位于不同的地理位置&#xff0c;但需要进行紧密的业务协…