Leetcode每日一题学习训练——Python3版(最小化旅行的价格总和)

news2025/2/26 2:36:42

版本说明

当前版本号[20231206]。

版本修改说明
20231206初版

目录

文章目录

  • 版本说明
  • 目录
  • 最小化旅行的价格总和
    • 理解题目
    • 代码思路
    • 参考代码

原题可以点击此 2646. 最小化旅行的价格总和 前去练习。

最小化旅行的价格总和

现有一棵无向、无根的树,树中有 n 个节点,按从 0n - 1 编号。给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示树中节点 aibi 之间存在一条边。

每个节点都关联一个价格。给你一个整数数组 price ,其中 price[i] 是第 i 个节点的价格。

给定路径的 价格总和 是该路径上所有节点的价格之和。

另给你一个二维整数数组 trips ,其中 trips[i] = [starti, endi] 表示您从节点 starti 开始第 i 次旅行,并通过任何你喜欢的路径前往节点 endi

在执行第一次旅行之前,你可以选择一些 非相邻节点 并将价格减半。

返回执行所有旅行的最小价格总和。

示例 1:

img

输入:n = 4, edges = [[0,1],[1,2],[1,3]], price = [2,2,10,6], trips = [[0,3],[2,1],[2,3]]
输出:23
解释:
上图表示将节点 2 视为根之后的树结构。第一个图表示初始树,第二个图表示选择节点 0 、2 和 3 并使其价格减半后的树。
第 1 次旅行,选择路径 [0,1,3] 。路径的价格总和为 1 + 2 + 3 = 6 。
第 2 次旅行,选择路径 [2,1] 。路径的价格总和为 2 + 5 = 7 。
第 3 次旅行,选择路径 [2,1,3] 。路径的价格总和为 5 + 2 + 3 = 10 。
所有旅行的价格总和为 6 + 7 + 10 = 23 。可以证明,23 是可以实现的最小答案。

示例 2:

img

输入:n = 2, edges = [[0,1]], price = [2,2], trips = [[0,0]]
输出:1
解释:
上图表示将节点 0 视为根之后的树结构。第一个图表示初始树,第二个图表示选择节点 0 并使其价格减半后的树。 
第 1 次旅行,选择路径 [0] 。路径的价格总和为 1 。 
所有旅行的价格总和为 1 。可以证明,1 是可以实现的最小答案。

提示:

  • 1 <= n <= 50
  • edges.length == n - 1
  • 0 <= ai, bi <= n - 1
  • edges 表示一棵有效的树
  • price.length == n
  • price[i] 是一个偶数
  • 1 <= price[i] <= 1000
  • 1 <= trips.length <= 100
  • 0 <= starti, endi <= n - 1

理解题目

首先需要构建一棵树,然后使用动态规划来计算每个节点作为根节点时的最小价格总和。

在计算过程中,可以选择一些非相邻节点并将价格减半。

简单来说就是:

  1. 构建树结构
  2. 初始化动态规划数组
  3. 遍历所有旅行,计算每个节点作为根节点时的最小价格总和
  4. 返回最小价格总和

代码思路

  1. 首先,根据给定的边信息构建一个邻接表来表示树结构。每个节点都有一个子节点列表,用于存储与该节点相连的其他节点。

    def minimumTotalPrice(self, n: int, edges: List[List[int]], price: List[int], trips: List[List[int]]) -> int:
            # 构建邻接表表示树结构
            children = [[] for _ in range(n)]
            for edge in edges:
                children[edge[0]].append(edge[1])
                children[edge[1]].append(edge[0])
    
  2. 然后,初始化一个计数器数组 count,用于记录每个节点在行程中出现的次数。

      # 初始化每个节点的计数器
            count = [0] * n
    
  3. 接下来,使用深度优先搜索(DFS)遍历树结构,计算从起点到终点的路径上的节点数量。在遍历过程中,如果到达终点节点,则将该节点的计数器加一。

     # 深度优先搜索,计算从起点到终点的路径上的节点数量
            def dfs(node: int, parent: int, end: int) -> bool:
                if node == end:
                    count[node] += 1
                    return True
                for child in children[node]:
                    if child == parent:
                        continue
                    if dfs(child, node, end):
                        count[node] += 1
                        return True
                return False
    
  4. 遍历所有行程,对于每个行程的起点和终点,调用 DFS 函数来计算从起点到终点的路径上的节点数量,并将结果累加到对应节点的计数器中。

    # 遍历所有行程,计算每个节点在行程中出现的次数
            for [x, y] in trips:
                dfs(x, -1, y)
    
  5. 最后,使用动态规划(DP)来计算每个节点作为根节点时的最小总价格。在 DP 函数中,首先计算当前节点作为根节点时的总价格,然后递归地计算其子节点作为根节点时的最小总价格,并根据题目要求进行选择。

      # 动态规划,计算每个节点作为根节点时的最小总价格
            def dp(node: int, parent: int) -> List[int]:
                res = [
                    price[node] * count[node], price[node] * count[node] // 2
                ]
                for child in children[node]:
                    if child == parent:
                        continue
                    [x, y] = dp(child, node)
                    # node 没有减半,因此可以取子树的两种情况的最小值
                    # node 减半,只能取子树没有减半的情况
                    res[0], res[1] = res[0] + min(x, y), res[1] + x
                return res
    
  6. 最终返回根节点为0时的最小总价格。

        # 返回根节点为0时的最小总价格
        return min(dp(0, -1))

参考代码

这段代码是一个解决旅行商问题(TSP)的算法,通过构建树结构、计算节点出现次数和使用动态规划来计算旅行商问题的最小总价格。

class Solution:
    def minimumTotalPrice(self, n: int, edges: List[List[int]], price: List[int], trips: List[List[int]]) -> int:
        children = [[] for _ in range(n)]
        for edge in edges:
            children[edge[0]].append(edge[1])
            children[edge[1]].append(edge[0])
        
        count = [0] * n
        def dfs(node: int, parent: int, end: int) -> bool:
            if node == end:
                count[node] += 1
                return True
            for child in children[node]:
                if child == parent:
                    continue
                if dfs(child, node, end):
                    count[node] += 1
                    return True
            return False
        
        for [x, y] in trips:
            dfs(x, -1, y)
        
        def dp(node: int, parent: int) -> List[int]:
            res = [
                price[node] * count[node], price[node] * count[node] // 2
            ]
            for child in children[node]:
                if child == parent:
                    continue
                [x, y] = dp(child, node)
                # node 没有减半,因此可以取子树的两种情况的最小值
                # node 减半,只能取子树没有减半的情况
                res[0], res[1] = res[0] + min(x, y), res[1] + x
            return res

        return min(dp(0, -1))

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

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

相关文章

LeetCode Hot100 207.课程表

题目&#xff1a; 你这个学期必须选修 numCourses 门课程&#xff0c;记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出&#xff0c;其中 prerequisites[i] [ai, bi] &#xff0c;表示如果要学习课程 ai 则 必须 先学习…

人工智能在警务工作中的运用

AI 能否帮助警察打击犯罪&#xff1f; 执法部门负责维护公共安全&#xff0c;他们必须处理随之而来的所有挑战。幸运的是&#xff0c;警察可以依靠技术来处理很多工作。近几年来&#xff0c;尤其是人工智能技术在全球变成了警务工作中的一个重要部分。 随着基于 AI 的警务技术…

如何在Java中实现多条件排序

文章目录 前言一、在Java中使用Comparator接口实现多条件排序二、视频讲解总结 前言 多条件排序是一个复杂而实用的技术问题&#xff0c;它涉及到算法、数据结构等多个领域。 在实际工作中&#xff0c;我们常常需要根据多个条件对数据进行排序&#xff0c;以达到最优化的效果。…

桶排序去重

题目&#xff1a; #include<stdio.h> int main() { int a[1001], n, i, t; for (i 1;i < 1000;i) { a[i] 0;//初始化 } scanf("%d", &n);//读入n for (i 1;i < n;i)//循环读入n个图书的ISBN号 { scanf(&…

ABAP 字符串空白值保留长度或者用其他字符替代

保留空白值在字符串的长度。 DATA lv_char1 TYPE string VALUE Hello. DATA lv_char2 TYPE string VALUE World. DATA LV_CHAR3 TYPE C LENGTH 50.DATA(lv_string3) |{ lv_char1 } { lv_char2 }!|.WRITE: / lv_string3.DATA(lv_string2) lv_char1 && | { lv_char3 } …

分库分表详解

分库分表很常见&#xff0c;但这些问题90%的人都答不全 分库分表&#xff0c;是企业里面比较常见的针对高并发、数据量大的场景下的一种技术优化方案&#xff0c;也是一个非常高频的面试题。但是&#xff0c;因为很多人其实并没有非常丰富的分库分表的经验&#xff0c;所以能把…

虚拟线程原理及性能分析

一、背景 JDK21 在 9 月 19 号正式发布&#xff0c;带来了较多亮点&#xff0c;其中虚拟线程备受瞩目&#xff0c;毫不夸张的说&#xff0c;它改变了高吞吐代码的编写方式&#xff0c;只需要小小的变动就可以让目前的 IO 密集型程序的吞吐量得到提升&#xff0c;写出高吞吐量的…

甘草书店:#8 2023年11月22日 星期三「“说一套做一套”的甘草与麦田」

最近与甘草书店的投资方和意向投资方沟通&#xff0c;听取了来自不同领域不同人群的观点。他们讲的都有道理&#xff0c;但他们说的都不是甘草。就像“麦田”成立之前&#xff0c;世间没有“麦田”一样&#xff1b;“甘草”出现之前&#xff0c;世间没有也没有“甘草”。 故事…

UDP多人群聊

一&#xff0c;创建类 二&#xff0c;类 1&#xff0c;Liao类 import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.net.*; import java.io.IOException; import java.lang.String; public class Liao extends JFrame{ private static fi…

智慧景区(园区)数字孪生可视化GIS解决方案

随着技术的日新月异&#xff0c;景区日常管理及运营中使用到的智慧化工具越来越丰富&#xff0c;智慧化硬件设备也越来越多&#xff0c;而其中各个管理系统往往又是相互独立&#xff0c;形成一个个数据孤岛。智慧景区管理平台就是将各个孤岛中的数据及功能汇集起来&#xff0c;…

【数据结构】动态规划(Dynamic Programming)

一.动态规划&#xff08;DP&#xff09;的定义&#xff1a; 求解决策过程&#xff08;decision process&#xff09;最优化的数学方法。 将多阶段决策过程转化为一系列单阶段问题&#xff0c;利用各阶段之间的关系&#xff0c;逐个求解。 二.动态规划的基本思想&#xff1a; …

Kubernetes常用工作负载控制器

文章目录 一、常用负载控制器是什么二、Deployment控制器1.介绍2.使用流程3.应用部署4.应用升级5.滚动升级实现原理&#xff08;replicaset控制器&#xff09;6.滚动升级实现流程7.滚动升级策略8.应用实例扩容和缩容9.应用发布失败回滚10.应用下线 三、DaemonSet控制器四、Job控…

elk+kafka+filebeat

elk1 cd /opt 把filebeat投进去 tar -xf filebeat-6.7.2-linux-x86_64.tar.gz mv filebeat-6.7.2-linux-x86_64 filebeat cd filebeat/ yum -y install nginx systemctl restart nginx vim /usr/share/nginx/html/index.html this is nginx cp filebeat.yml filebeat.yml.…

在Vivado 仿真器中搭建UVM验证环境(不需要联合modelsim)

Vivado 集成设计环境支持将通用验证方法学 (UVM) 应用于 Vivado 仿真器。Vivado 提供了预编译的 UVM V1.2 库。 &#xff08;1&#xff09;在 Vivado 2019.2 中创建新 RTL 工程。 &#xff08;2&#xff09;单击“添加目录 (Add Directories)”以将“src”和“verif”目录添加…

LLM大语言模型(一):ChatGLM3-6B本地部署

目录 前言 本机环境 ChatGLM3代码库下载 模型文件下载 修改为从本地模型文件启动 启动模型网页版对话demo 超参数设置 GPU资源使用情况 &#xff08;网页对话非常流畅&#xff09; 前言 LLM大语言模型工程化&#xff0c;在本地搭建一套开源的LLM&#xff0c;方便后续的…

Python实现FA萤火虫优化算法优化LightGBM分类模型(LGBMClassifier算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 萤火虫算法&#xff08;Fire-fly algorithm&#xff0c;FA&#xff09;由剑桥大学Yang于2009年提出 , …

空间金字塔池化(SPP,Spatial Pyramid Pooling)系列

空间金字塔池化的作用是解决输入图片大小不一造成的缺陷&#xff0c;同时在目标识别中增加了精度。空间金字塔池化可以使得任意大小的特征图都能够转换成固定大小的特征向量&#xff0c;下面针对一些典型的空间金字塔进行盘点。 部分图片来自blog:空间金字塔池化改进 SPP / SP…

第二十一章总结

一、网络通信&#xff1a; 1.网络程序设计基础&#xff1a;网络程序设计编写的是与其他计算机进行通信的程序。 1.1局域网与互联网&#xff1a;为了实现两台计算机的通信&#xff0c;必须用一个网络线路连接两台计算机 2.网络协议&#xff1a;网络协议规定了计算机之间连接的…

【精选】WebLogic-CVE-2017-3506

下载地址&#xff1a; https://github.com/Al1ex/CVE-2017-3506https://github.com/Al1ex/CVE-2017-3506 1.weblogic wls-wsat组件远程命令执行&#xff08;CVE-2017-3506&#xff09; 复现&#xff1a; ┌──(root&#x1f480;kali)-[~/routing/红日2/CVE-2017-3506-mai…

C++利剑string类(详解)

前言&#xff1a;大家都知道在C语言里面的有 char 类型&#xff0c;我接下来要讲的 string 类功能是使用 char 类型写的类&#xff0c;当然这个是C官方写的&#xff0c;接下来我们将会学会使用它&#xff0c;我们会发现原来 char 这种类型是还能这么好用&#xff0c;授人以…