20天拿下华为OD笔试之【回溯】2023Q1A-基站维修工程师【欧弟算法】全网注释最详细分类最全的华为OD真题题解

news/2024/11/23 6:40:11/

文章目录

  • 【回溯】2023Q1A-基站维修工程师
  • 题目描述与示例
    • 题目
    • 输入
    • 输出描述
    • 示例一
      • 输入
      • 输出
      • 说明
  • 解题思路
    • 剪枝优化
  • 时空复杂度
  • 代码
    • 解法一:回溯(无剪枝优化)
    • 解法二:回溯(剪枝优化)

【回溯】2023Q1A-基站维修工程师

题目描述与示例

题目

小王是一名基站维护工程师,负责某区域的基站维护。 某地方有 n 个基站,1 < n < 10,已知各基站之间的距离 s0 < s < 500,并且基站 x 到基站 y 的距离,与基站 y 到 基站 x 的距离并不一定会相同。 小王从基站 0 出发,途经每个基站 1 次,然后返回基站 0 ,需要请你为他选择一条距离最短的路。

输入

站点数 n 和各站点之间的距离,均为整数。

3     // 表示站点数
0 2 1 // 表示站点0到各站点的路程
1 0 2 // 表示站点1到各站点的路程
2 1 0 // 表示站点3到各站点的路程

输出描述

最短路程的数值。

示例一

输入

3
0 2 1
1 0 2
2 1 0

输出

3

说明

路线为0 -> 2 -> 1 -> 0,距离为所有路线最小 1 + 1 + 1 = 3。如果选择路线0 -> 1 -> 2 -> 0,距离为 2 + 2 + 2 = 6

解题思路

这道题本质上是一道排列类型的回溯问题。

路径的终点和起点是都定好的,均为基站0,且其他基站能且仅能通过1次。所以我们只需要考虑剩余n-1个基站的全排列方式即可,即一共有(n-1)!种排列方式。

假设一共有 4 个基站,我们有且只有以下6种可能的路径:

0 -> 1 -> 2 -> 3 -> 0
0 -> 1 -> 3 -> 2 -> 0
0 -> 2 -> 1 -> 3 -> 0
0 -> 2 -> 3 -> 1 -> 0
0 -> 3 -> 1 -> 2 -> 0
0 -> 3 -> 2 -> 1 -> 0

所以可以使用回溯的办法,暴力地枚举出所有路径的距离和,并且获得所有距离和中的最小值即可。

剪枝优化

本题还可以进行剪枝优化。思路非常直接:如果某条路径的距离和path_sum已经大于等于当前的ans了,那么这条路径再往下延申,也一定会比ans更大,那么这条路径再往下搜寻就没有意义了,可以进行剪枝。

时空复杂度

时间复杂度:O(N!)。一共有(n-1)!条路径需要计算路径和。

空间复杂度:O(N)。忽略调用递归函数时编译栈所占空间,仅考虑检查数组所占用空间。

代码

解法一:回溯(无剪枝优化)

# 题目:2023Q1A-基站维修工程师
# 作者:闭着眼睛学数理化
# 算法:回溯-无剪枝优化
# 代码看不懂的地方,请直接在群上提问from math import infn = int(input())
mat = list()
for i in range(n):mat.append(list(map(int, input().split())))# 用于判断某一节点是否被包含在当前路径中的检查数组
check_list = [False] * n
# 初始化位置0已经被包含在路径中
check_list[0] = True
# 初始化
ans = inf# 回溯函数
def dfs(mat, check_list, cur_idx, path_sum):# 声明ans为全局变量,需要反复地被更新global ans# 终止递归条件:# 当check_list中所有值均为True,说明得到了一条经过了所有点的路径# 当前路径和path_sum还需要再加上从位置cur_idx去往位置0的距离if all(check_list):ans = min(ans, path_sum + mat[cur_idx][0])return# 横向遍历cur_idx到下一个点nxt_idx的所有距离for nxt_idx, val in enumerate(mat[cur_idx]):# 只有当nxt_idx还未存在于路径中,cur_idx才可以到达if check_list[nxt_idx] == False:# 状态更新:# 1. 标记下一个点nxt_idx已经存在于路径中# 2. 将从cur_idx到nxt_idx的距离val加入当前路径总和中check_list[nxt_idx] = Truepath_sum += val# 回溯:对下一个点nxt_idx进行递归dfs(mat, check_list, nxt_idx, path_sum)# 回滚:# 1. 标记下一个点nxt_idx从路径中删除# 2. 将从cur_idx到nxt_idx的距离val从当前路径总和中减去check_list[nxt_idx] = Falsepath_sum -= val# 调用递归函数的入口,最开始cur_idx = 0,path_sum = 0
dfs(mat, check_list, 0, 0)
print(ans)

解法二:回溯(剪枝优化)

# 题目:2023Q1A-基站维修工程师
# 作者:闭着眼睛学数理化
# 算法:回溯-剪枝优化
# 代码看不懂的地方,请直接在群上提问from math import infn = int(input())
mat = list()
for i in range(n):mat.append(list(map(int, input().split())))# 用于判断某一节点是否被包含在当前路径中的检查数组
check_list = [False] * n
# 初始化位置0已经被包含在路径中
check_list[0] = True
# 初始化
ans = inf# 回溯函数
def dfs(mat, check_list, cur_idx, path_sum):# 声明ans为全局变量,需要反复地被更新global ans# 剪枝优化:# 如果当前路径和path_sum已经大于等于当前ans# 这条路径再往下搜寻没有意义,不可能比ans更小,进行剪枝,终止当前路径继续往下搜寻if path_sum >= ans:return# 终止递归条件:# 当check_list中所有值均为True,说明得到了一条经过了所有点的路径# 当前路径和path_sum还需要再加上从位置cur_idx去往位置0的距离if all(check_list):ans = min(ans, path_sum + mat[cur_idx][0])return# 横向遍历cur_idx到下一个点nxt_idx的所有距离for nxt_idx, val in enumerate(mat[cur_idx]):# 只有当nxt_idx还未存在于路径中,cur_idx才可以到达if check_list[nxt_idx] == False:# 状态更新:# 1. 标记下一个点nxt_idx已经存在于路径中# 2. 将从cur_idx到nxt_idx的距离val加入当前路径总和中check_list[nxt_idx] = Truepath_sum += val# 回溯:对下一个点nxt_idx进行递归dfs(mat, check_list, nxt_idx, path_sum)# 回滚:# 1. 标记下一个点nxt_idx从路径中删除# 2. 将从cur_idx到nxt_idx的距离val从当前路径总和中减去check_list[nxt_idx] = Falsepath_sum -= val# 调用递归函数的入口,最开始cur_idx = 0,path_sum = 0
dfs(mat, check_list, 0, 0)
print(ans)

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

相关文章

C语言——1.入门须知

文章目录 1.C语言的简要概述1.1.C语言类比自然语言1.2.计算机语言的发展1.3.C语言在当今的地位1.4.C语言的优势和劣势1.4.1.C语言的优势1.4.2.C语言的劣势 2.C语言的应用场景3.C语言的学习路径3.1.学习目的3.2.学习路径3.3.学习资源3.3.1.推荐书籍3.3.2.推荐课程3.3.3.推荐题库…

【Go入门】 Go的http包详解

【Go入门】 Go的http包详解 前面小节介绍了Go怎么样实现了Web工作模式的一个流程&#xff0c;这一小节&#xff0c;我们将详细地解剖一下http包&#xff0c;看它到底是怎样实现整个过程的。 Go的http有两个核心功能&#xff1a;Conn、ServeMux Conn的goroutine 与我们一般编…

Unity减少发布打包文件的体积(二)——设置WebGL发布时每张图片的压缩方式

一个项目在发布成WebGL后&#xff0c;其体积至关重要&#xff0c;体积太大&#xff0c;用户加载会经历一个漫长的等待…轻则骂娘&#xff0c;重则用脚把电脑踢烂(扣质保金)… 那么如何减少发布后的体积呢&#xff0c;本文从图片的压缩开始入手。 前传回顾&#xff1a; Unity减…

VS 将 localhost访问改为ip访问

项目场景&#xff1a; 使用vs进行本地调试时需要多人访问界面,使用ip访问报错 问题描述 vs通过ip访问报错 虚拟机或其它电脑不能正常打开 原因分析&#xff1a; 原因是vs访问规则默认是iis,固定默认启动地址是localhost 解决方案&#xff1a; 1.vs项目启动之后会出现这个 右…

mac系统安装docker desktop

Docker的基本概念 Docker 包括三个基本概念: 镜像&#xff08;Image&#xff09;&#xff1a;相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。比如说nginx,mysql,redis等软件可以做成一个镜像。容器&#…

go的字符切片和字符串互转

Go 1.21 // 返回一个Slice&#xff0c;它的底层数组自ptr开始&#xff0c;长度和容量都是len func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType // 返回一个指针&#xff0c;指向底层的数组 func SliceData(slice []ArbitraryType) *ArbitraryType // 生成一…

MFC/QT 一些快要遗忘的细节:

1&#xff1a;企业应用中&#xff0c;MFC平台除了用常见的对话框模式还有一种常用的就是单文档模式&#xff0c; 维护别人的代码&#xff0c;不容易区分,其实找与程序同名的cpp就知道了&#xff0c;比如项目名称为 DoCMFCDemo&#xff0c;那么就看BOOL CDocMFCDemoApp::InitI…

创新研报|新业务发展是CEO推动企业增长的必要选择 – Mckinsey研究

&#x1f50d;&#x1f4c8; 创新研究报告 |新业务拓展&#xff1a;CEO推动企业成长的必然选择 – 麦肯锡研究 &#x1f525;&#x1f4bc; 所有执行长和商界领袖请注意&#xff01;您是否正在寻找为您的组织释放成长机会的钥匙&#xff1f; &#x1f310; 麦肯锡最近的一份研究…