python 基础知识点(蓝桥杯python科目个人复习计划47)

2024-02-21 13:44

本文主要是介绍python 基础知识点(蓝桥杯python科目个人复习计划47),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今日复习内容:树形DP

自上而下的树形动态规划(DP)是一种解决树形结构问题的有效方法。在树形结构中,每个节点通常有0个或多个子节点,而且节点之间存在着特定的父子关系。树形DP的目标是通过叶子节点逐步向上计算,根据根节点的最优解或者其他需要的信息。

1.问题建模

首先需要将问题转化为树形结构,确定节点之间的父子关系以及每个节点的属性和目标。

确定问题的子问题定义,即每个节点需要解决的子问题是什么。

2.状态定义

定义动态规划状态,通常与问题的子问题有关。

状态是每个节点的某种属性,也可以是节点之间的关系或者路径。

3.状态转移方程

根据子问题的定义和状态的定义,建立状态转移方程。

状态转移方程描述了从子问题到父问题的转移过程,通常使用递归或者迭代的方式进行定义。

4.自底而上计算

从叶子节点开始计算,逐步向上计算父节点的状态,直到算出根节点的状态或者所需的信息。

5.结果输出

根据问题的具体要求,从根节点的状态或者其他节点的状态中获取所需的信息或者最优解。

6.优化技巧

可以利用记忆化搜索或者动态规划数组来优化计算过程,避免重复计算子问题。

如果树的结构较大,可以考虑剪枝或者其他优化策略来减少计算复杂度。


最大独立集问题是在给定的图中寻找一个最大的顶点集合,使得集合中的任意两个顶点都不相邻(即没有边连接)。

来举个例子,我用的是贪心算法。

问题描述:假设有一个无向图,其顶点集合为{1,2,3,4,5,6},边集合为{(1,2),(1,3),(2,3),(2,4),(3,5),(4,5),(4,6)},我们的目标是找到这个图中的一个最大独立集。

一种可能的最大独立集是{1,4,5},因为这个集合中的任意两个顶点都不相邻。

我们可使用贪心算法来解决这个问题。贪心算法的基本思路是每次选择一个顶点加入独立集中,并移除该顶点的所有相邻顶点。通过反复执行这个过程,直到所有顶点都被考虑到为止。

在这个示例中,我们可以按照以下步骤来构建最大独立集。

1.选择顶点1加入独立集,移除与顶点1相邻的2和3;

2.选择顶点4加入独立集,移除与顶点4相邻的2和5;

3.选择顶点5加入独立集,移除与顶点5相邻的3和4;

4.所得的独立集是{1,4,5}。


接下来做几个题:

例题1:蓝桥舞会

题目描述:

蓝桥公司一共有n名员工,编号分别为1 - n。

他们之间的关系就像一棵以董事长为根的树,父节点就是子节点的直接上司。

每个员工有一个快乐指数ai。

现蓝桥董事会决定举办一场蓝桥舞会让员工们在工作之余享受美好时光,不过对于每个员工,他们都不愿意与自己的直接上司一起参会。

董事会希望舞会的所有参会员工的快乐指数总和最大,请你求出这个最大值。

输入描述:

输入的第一行是一个整数n,表示蓝桥公司的员工数。

第二行包含n个整数,分别表示第i个员工的快乐指数ai。

接下来n - 1行每行包含两个整数u和v,表示v是u的直接上司。

1 <= u,v,ai <= n <= 10^5

输出描述:

输出一个整数,表示答案。

参考答案:

n = int(input())
happy = [0] + list(map(int, input().split()))
tree = [[] for i in range(n + 1)]
fa = [0] * (n + 1)
for i in range(n - 1):u, v = map(int, input().split())tree[v].append(u)fa[u] = 1  # 我是u!我有爹!
dp = [[0] * 2 for _ in range(n + 1)]# 直接上司不行,但是间接上司可以,所以并不代表选了这层,下下一层就不能选了。
def dfs(i):dp[i][0] = 0dp[i][1] = happy[i]  # 首先,宣誓本节点的值。if tree[i] == []:  # 爆搜到底根。returnfor j in tree[i]:  # 对子节点的最优子结构进行累加。dfs(j)dp[i][0] += max(dp[j][0], dp[j][1])  # 不选,那么后面都可以选。dp[i][1] += dp[j][0]  # 选了,他的子节点不能选了。最优子结构锁定在dp[j][0]for i in range(1, n + 1):if fa[i] == 0:treeok = idfs(i)  # 没有爸爸的人,就是根节点。
print(max(dp[treeok][0], dp[treeok][1]))

运行结果: 

以下是我对代码的理解:

1.读取输入

n = int(input()):n表示员工的数量

happy = [0] + list(map(int,input().split())):读取每个员工的快乐指数,并存储在happy数组中

tree = [[ ] for i in range(1,n + 1)]:创建了一个空的树状结构tree,用于表示员工之间的关系

fa = [0] * (n + 1):fa数组用于标记每个员工是否有父节点

for i in range(n - 1):循环从第一个员工到倒数第二个员工(因为最后一个员工没有直接上司,不需要处理)

u,v = map(int,input().split()):从输入中读取一对整数u和v,表示v是u的直接上司

tree[v].append(u):将员工u添加到员工v的直接下属列表中,表示员工u是员工v的直接下属

fa[u] = 1:标记员工u有直接上司,因为后面会通过判断fa[u]来确定根节点

dp[[0] * 2 for i in range(n + 1)]:创建一个二维数组,其中每行表示一个节点,每行有两个元素,分别表示不选择该节点和选择该节点时的状态值,其中dp[i][0]表示不选择节点i时的最大快乐指数,dp[i][1]表示选择该节点时的最大快乐指数。

接下来用深度优先搜索dfs(i),用于计算以节点i为根的子树中的最大快乐指数

dp[i][0] = 0:初始化节点i不被选择时的最大快乐指数为0

dp[i][1] = happy[i]:初始化节点i被选择时的最大快乐指数为节点i的快乐指数

if tree[i] == []:检查节点i是否为叶子节点,即没有子节点的情况

return:如果是叶子节点,函数直接返回,因为叶子节点的最大快乐指数就是节点本身的快乐指数

for j in tree[i]:遍历节点i的所有子节点j

dfs(j):递归调用dfs函数,计算以子节点j为根的子树中的最大快乐数

dp[i][0] += max(dp[j][0],dp[j][1]):更新不选择节点i时的最大快乐指数(如果不选择节点i,则可以选择其子节点中的最大快乐指数)

dp[i][1] += dp[j][0]:更新选择节点i时的最大快乐指数(如果选择节点i,则不能选择其子节点,所以最大快乐指数是节点i的快乐指数其所有子节点的不被选择时的最大快乐指数)

for i in range(1,n + 1):遍历所有员工编号,从1到n

if fa[i] == 0:检查是否有直接上司,即是否为根节点,如果fa[i] 为0,表示没有直接上司,说明员工i是根节点

treeok = i:将根节点的编号保存在变量treeok中

dfs(i):调用深度优先搜索函数,计算以根节点i为根的子树的最大快乐指数

最后,输出整个树的最大快乐指数,,即根节点的最大快乐指数。

通过max(dp[treeok][0],dp[treeok][1]):取选择和不选择时的最大值。


例题2:生命之树

题目描述:

在x森林里,上帝创造了生命之树。

他在每棵树的每个节点(叶子也称为一个节点)上,都标了一个整数,代表这个点的和谐值。

上帝要在这棵树内选出一个非空节点集s,使得s中的任意两个点a,b,都存在一个点列a,v1,v2,...,vk,b,使得这个点列中的每个点都是s里的元素,且序列中相邻两个点间有一条边相连。

在这个前提下,上帝要使得s中的点所对应的整数的和尽量大。

这个最大的和就是上帝给生命之树的评分。

经过atm的努力,他已经知道了上帝给每棵树每个节点上的整数。但由于atm不善于计算,他不知第怎样有效地求评分。他需要你为他写一个程序来计算一棵树的分数。

输入描述:

第一行一个整数n表示这棵树有n个节点。

第二行n个整数,一次表示每个节点的评分,接下来n - 1行,每行两个整数u,v,表示存在一条u到v的边。由于这是一棵树,所有不存在环。

其中,0 < n <= 10^5,每个节点的评分的绝对值不超过10^6.

输出描述:

输出一行一个数,表示上帝给这棵树的分数。

参考答案:

import sys
sys.setrecursionlimit(100000)
n=int(input())
aList=[0] + [int(i) for i in input().split()]
tree=[[]for i in range(n+1)]
root_max=[0 for i in range(n+1)]
for i in range(n-1):m,n=map(int,input().split())tree[m].append(n)tree[n].append(m)
def dfs(dad,son):root_max[son]=aList[son]for i  in tree[son]:if i !=dad:root_max[i]=dfs(son,i)if root_max[i]>0:root_max[son]+=root_max[i]return root_max[son]
dfs(0,1)
print(max(root_max))

以下是我自己的思路:

sys.setrecursionlimit(100000):这行代码设置了递归的最大深度设置,防止递归调用栈溢出

n = int(input()):输入整数n,表示树的节点数

alist = [0] + [int(i) for i in input().split()]:输入每个节点的评分,将它们储存在列表alist中。这里使用列表推导式和split()方法将输入的评分转换为整数列表,并在列表开头添加一个占位符0

tree = [[ ] for i in range(n + 1)]:创建一个空的列表,用于存储树的邻节点,其中,tree[i]存储与节点i相邻的节点列表。

root_max = [0 for i in range(n + 1)]:创建一个长度为n + 1的列表,用于存储以每个节点为根的子树的最大评分

接下来构建树的邻接表表示,其中每个节点的邻居节点存储在列表中。

for i in range(n - 1):这是一个循环,遍历了n - 1次,因为一棵树的边数总是比节点数少一个

“一棵树的边数总是比节点数少一个”:

这句话的意思是在一个无向树中,边的数量总数比节点的数量少一个。这是因为树 是一个连通且无环的图,每个节点都与其他节点通过边相连,但是没有形成环路。考虑到树的性质,可以通过归纳法来得出这个结论。

基础情况:当只有一个节点时,边数为0,符合条件。

归纳假设:假设对于有n个节点的树,边的数量总是n - 1。

归纳步骤:考虑一棵含义n + 1个节点的树。在这棵树中选择任意一个节点作为根节点,将树分成以该节点为根的子树和其他子树。此时,原树中包含n + 1个节点,将根节点和其余的子树看作独立的节点,则按归纳假设,每个子树都含有k个节点,其中1 <= k <= n。根据归纳假设,每个子树的边数为k - 1,总共有n个子树,因此总边数为n。

归纳结论:对于含有n+1个节点数,边的数量也是n。

因此,一棵树的边数总是比节点数少一个。

m,n = map(int,input().split()):从输入中获取一条边的两个节点m和n

tree[m].append(n):将节点n添加到节点m的邻居列表中,表示节点m与节点n之间存在一条边

tree[n].append(m):同样,将节点m添加到n的邻居列表中,因为树的边是双向的

通过这个循环,根据输入的边信息,成功构建了树的邻接表表示。这样,后续在DFS中,可以方便地遍历每个节点的邻居节点,实现相应的计算。

def dfs(dad,son):定义了一个递归的DFS函数,用于计算以son为根的子树的最大评分

root_max[son] = alist[son]:初始化以节点son为根的子树的最大评分为节点son的评分

for i in tree[son]:遍历节点son旁边的所有邻居节点i

if i != dad:检查当前节点i是否为父节点,避免向上回溯。

root_max[i]  = dfs(son,i):递归调用dfs函数计算以节点i为根的子树的最大评分,并且将结果存储在root_max[i]中。

if root_max[i] > 0:如果子树的最大评分大于0,则将其累加到当前节点son的评分中

return root_max[son]:返回以节点son为根的子树的最大评分

dfs(0,1):调用DFS函数,计算以节点1为根的整棵树的最大评分

print(max(root_max)):输出整棵树的最大评分,即取root_max列表中的最大值。


OK,这个知识点我学了好久,暂时只会这些。

下一篇继续!

这篇关于python 基础知识点(蓝桥杯python科目个人复习计划47)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/731969

相关文章

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Python Websockets库的使用指南

《PythonWebsockets库的使用指南》pythonwebsockets库是一个用于创建WebSocket服务器和客户端的Python库,它提供了一种简单的方式来实现实时通信,支持异步和同步... 目录一、WebSocket 简介二、python 的 websockets 库安装三、完整代码示例1.

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专