Leetcode第451场周赛分析总结

在这里插入图片描述

题目链接

竞赛 - 力扣(LeetCode)全球极客挚爱的技术成长平台

题目解析

A. 3560. 木材运输的最小成本

AC代码

class Solution {
public:long long minCuttingCost(int n, int m, int k) {if (n > m) swap(n, m);  // n <= m;using ll = long long;ll ans = 0;if (m > k) {ans = static_cast<ll>(k) * (m - k);}return ans;}
};

思路分析

看完题目后发现,只有三辆车,题目保证有解,意味着最多只有一根木棍的长度会大于k从而被切割。接下来问题转换为,给定一根长度为n>k的木棍,将其切割为x+y=n两部分,求z=x*y的最小值。我记得这是初中常见的一个约束,最大值出现在x=y=n/2的位置,最小值出现在两端。实际上z是x的一个二次函数,在其作用域内先增加后减少。

x的最大值是k,那么z的最小值就是k*(n-k)。

可惜在实现的时候没注意乘积会导致爆long long。其实返回值是long long就应该注意到的,不太应该。

灵神用Python代码一行就搞定了。Python的int操作起来是更方便一些。在算法竞赛有时会遇到一些大数运算(超过long long范围的运算),如果用C++需要手动模拟实现,用Python就方便很多。

Python的int类型可以处理任意精度的整数,理论上没有固定的大小限制,仅受限于计算机的可用内存(RAM)。

B. 3561.移除相邻字符

AC代码

class Solution {bool aux(char x, char y) {int diff = abs(x - y);return diff == 1 || diff == 25;}
public:string resultingString(string s) {string stk;for (auto c : s) {if (stk.empty()) {stk.push_back(c);} else {if (aux(stk.back(), c)) {stk.pop_back();} else {stk.push_back(c);}}}return stk;}
};

思路分析

注意到对于每次消除,至多影响前面的一个元素。每次都移除最左边的字符对,模拟了一下发现类似栈的性质,用栈模拟。

灵神的代码是先统一入栈,再考虑能否消除,在逻辑和实现上更简洁一些。

C. 3562. 折扣价交易股票的最大利润

AC代码

class Solution {
public:int maxProfit(int n, vector<int>& present, vector<int>& future, vector<vector<int>>& hierarchy, int budget) {vector<vector<int>> graph(n);for (auto &edge : hierarchy) {int u = edge[0] - 1, v = edge[1] - 1;graph[u].push_back(v);}function<vector<vector<int>>(int)> dfs;dfs = [&](int u) -> vector<vector<int>> {vector f(budget + 1, vector<int>(2, 0));vector g = f;for (int v : graph[u]) {auto fv = dfs(v);for (int b = budget; b >= 0; b--) {for (int bv = 0; bv <= b; bv++) {for (int k = 0; k < 2; k++) {g[b][k] = max(g[b][k], g[b - bv][k] + fv[bv][k]);}}}}for (int b = 0; b <= budget; b++) {for (int k = 0; k < 2; k++) {int bu = present[u] / (k + 1);if (bu <= b) {f[b][k] = max(g[b][0], g[b - bu][1] + future[u] - bu);} else {f[b][k] = g[b][0];}}}return f;};return dfs(0)[budget][0];}
};

思路分析

比赛时想到如果员工的关系是一个链表,那我可以类似背包问题进行处理,对于每由于每个员工只影响自己的下属(不会影响领导),所以有无后效性。需要最大化收益,所以有最优子结构。

每个员工有两个状态:

  • 可以使用的最大费用 b b b
  • 领导是否购买股票 k k k:0表示不买,1表示买

维护每个员工 u u u在给定状态 ( b , k ) (b, k) (b,k)下他和下属可以获得的最大收益 f f f v v v表示他的下属, c k c_k ck表示在领导买股票状态为 k k k的情况下购买股票的费用, p k p_k pk表示购买股票的收益。

f u ( b , k ) = m a x { f v ( b , 0 ) , f v ( b − c k , 1 ) + p k } f_u(b,k)= max\{f_v(b,0), f_v(b-c_k, 1)+p_k\} fu(b,k)=max{fv(b,0),fv(bck,1)+pk}

然后就可以进行状态转移。可是面对一个树结构,如果某员工决定给 t t t个下属 b b b费用让他们买股票,每个下属应该用多少费用才能获得最大收益呢?感觉得再需要一个回溯去搜索,简单想了一下会超时。

在认真听了灵神的讲解后,发现自己对背包问题的理解还是太浅显。

现在让我们专心考虑这个子问题,我们可以先得到每个下属在所有状态下的收益 f v ( b , k ) f_{v}(b,k) fv(b,k)(因为是在DP中),那对于某员工有 b b b费用的情况下,我们考虑前 i i i下属消耗多少费用才能获得最大收益 g i ( b , k ) g_i(b,k) gi(b,k)

之所以考虑前 i i i个是因为员工之间的选择除了消耗费用没有额外的影响,因此无后效性,求最大收益所以有最优子结构。我们发现,员工对他们下属的费用选择形成了一个0-1背包问题,不过与普通背包问题不同的是,每个物品的价格和收益不是固定的,而是一组。

现在问题转换为,对于某个员工,已经知道前 i − 1 i-1 i1个下属可以获得的最大收益 g i − 1 ( b , k ) g_{i-1}(b,k) gi1(b,k),对第 i i i个员工,应该消耗多少费用才能使得 g i ( b , k ) g_i(b,k) gi(b,k)最大,而这是一个贪心问题:

g i ( b , k ) = max ⁡ 0 ≤ b v ≤ b g i − 1 ( b − b v , k ) + f v i ( b v , k ) g_i(b,k)=\operatorname* {max}_{0\le b_v\le b} g_{i-1}(b-b_v,k)+f_{v_i}(b_v,k) gi(b,k)=0bvbmaxgi1(bbv,k)+fvi(bv,k)

在算到所有的 g ( b , k ) g(b,k) g(b,k)后,我们就知道了给所有下属b费用可以得到的最大收益,此时状态转移变成了:

f u ( b , k ) = m a x { g v ( b , 0 ) , g ( b − c k , 1 ) + p k } f_u(b,k)= max\{g_v(b,0), g(b-c_k, 1)+p_k\} fu(b,k)=max{gv(b,0),g(bck,1)+pk}

最后的问题在大的框架上是一个树型DP,每个节点上叶子到节点的状态转移是一个0-1背包问题,在这个0-1背包问题每个物体的选择上又是一个贪心问题。

经过一段时间的理解我才梳理出整个思路,最后的代码实现使用了0-1背包的滚动数组优化。自己的思维深度还是不够,同时也应该梳理思考的顺序,把已知、转换过程都用纸笔记录下来,可以帮助自己固定思维的结果,否则想着想着都糊涂了,人类的能力真是有局限的啊(迪奥笑)。

D. 3563. 移除相邻字符后字典序最小的字符串

AC代码

class Solution {static bool is_pair(char a, char b) {int diff = abs(a - b);return diff == 1 || diff == 25;}
public:string lexicographicallySmallestString(string s) {int n = s.size();vector dp2(n, vector<int>(n, 1));for (int i = 0; i < n; ++i) dp2[i][i] = 0;for (int l = 2; l <= n; ++l) {for (int i = 0; i + l - 1 < n; ++i) {int j = i + l - 1;dp2[i][j] = 0;if (is_pair(s[i], s[j])) {dp2[i][j] = dp2[i + 1][j - 1];if (dp2[i][j]) {continue;}}for (int k = i + 1; k < j; ++k) {dp2[i][j] = (dp2[i][k] && dp2[k + 1][j]);if (dp2[i][j]) {break;}}}}vector<string> dp(n + 1);for (int i = n - 1; i >= 0; --i) {auto &&ans = dp[i];ans.push_back(s[i]);ans.append(dp[i + 1]);for (int j = i + 1; j < n; ++j) {if (dp2[i][j]) {ans = min(ans, dp[j + 1]);}}}return dp[0];}
};

思路分析

比赛的时候没有看清楚题目,想当然的以为和第二题一样是从最左边删除,然后写了一通模拟,结果理所当然地过不了。在任意位置删除相邻对的情况下,显然已经不能模拟,只能考虑动态规划或者贪心。

由于求的是最小的串,所以有最优子结构。可是前面的删除似乎会影响后面的删除,这样看来是有后效性的,似乎看起来应该去思考贪心,但是贪心也没有很好的想法,起决定作用的是前面的字符,但前面的字符有可能是通过后面的字符会删除掉。

听了灵神的讲解后发现还是要沉下心去思考。我们上面觉得前面的字符可能和后面的字符配对删除所以有后效性,但是如果确定删除了就没有后效性了。尝试定义状态dp[i]为i开始的字符串删除配对后可以得到的最小字符串,考虑状态转移:

  • 如果s[i]不删除,那显然dp[i] = s[i] + dp[i + 1]

  • 关键在于s[i]如果可以删除呢,问题变成了s[i]开始多少个字符可以删掉。由于n很小,所以我们可以遍历[i, j]字符串,如果s[i, j]可以删除,dp[i]= min(dp[i], dp[j])。

    现在问题转换为,如何快速判断s[i, j]是否可以删除。灵神说可以联想到合法括号字符串(RBS),使用区间DP处理。难点在于,我联想不到,注意力薄弱。

最终问题通过区间DP处理出哪些区间可以被消除,再用线性DP算出以某个字符开始可以得到的最小字符串。

总结

对这种需要多重转换组合的问题,一旦卡住就没法继续下去。以后对于每个思考的方向,物理化自己的思维过程,把卡住的地方转换成新的问题重新思考,不要卡住了就想来想去没有进展。

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

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

相关文章

Linux中的shell脚本

什么是shell脚本 shell脚本是文本的一种shell脚本是可以运行的文本shell脚本的内容是由逻辑和数据组成shell脚本是解释型语言 用file命令可以查看文件是否是一个脚本文件 file filename 脚本书写规范 注释 单行注释 使用#号来进行单行注释 多行注释 使用 : " 注释内容…

PHP与MYSQL结合中中的一些常用函数,HTTP协议定义,PHP进行文件编程,会话技术

MYSQL&#xff1a; 查询函数: 执行查询语句: 1.mysql_query("SQL语法"); 凡是执行操作希望拿到数据库返回的数据进行展示的(结果返回: 数据结果); 2.执行结果的处理:成功为结果集&#xff0c;失败为false; 成功返回结果:SQL指令没有错误&#xff0c;但是查询结果…

数学分析——一致性(均匀性)和收敛

目录 1. 连续函数 1.1 连续函数的定义 1.2 连续函数的性质 1.2.1 性质一 1.2.2 性质二 1.2.3 性质三 1.2.4 性质四 2. 一致连续函数 2.1 一致连续函数的定义 2.2 一致连续性定理(小间距定理)(一致连续函数的另一种定义) 2.3 一致连续性判定法 2.4 连…

湖北理元理律师事务所:企业债务优化的科学路径与人文关怀

湖北理元理律师事务所&#xff1a;企业债务优化的科学路径与人文关怀 在中小企业经营压力增大的背景下&#xff0c;如何平衡债务清偿与员工生计成为关键课题。湖北理元理律师事务所联合计划集团公司&#xff0c;为服务企业设计了一套兼顾法律合规性与民生保障的债务解决方案&a…

树莓派安装openwrt搭建软路由(ImmortalWrt固件方案)

&#x1f923;&#x1f449;我这里准备了两个版本的openwrt安装方案给大家参考使用&#xff0c;分别是原版的OpenWrt固件以及在原版基础上进行改进的ImmortalWrt固件。推荐使用ImmortalWrt固件&#xff0c;当然如果想直接在原版上进行开发也可以&#xff0c;看个人选择。 &…

一键净化Excel数据:高性能Python脚本实现多核并行清理

摘要 本文分享两个基于Python的Excel数据净化脚本&#xff0c;通过多进程并行技术清除工作表内不可见字符、批注、单元格样式等冗余内容&#xff0c;利用OpenPyXL实现底层操作&#xff0c;结合tqdm进度条和进程级任务分配&#xff0c;可快速处理百万级单元格数据。适用于数据分…

【Netty】EventLoopGroup

在Netty的ServerBootstrap中设置两个EventLoopGroup的作用是将网络操作的两个关键阶段分离到不同的线程组中处理&#xff0c;从而优化性能并简化并发控制。具体来说&#xff1a; 1. 两个EventLoopGroup的角色 第一个EventLoopGroup&#xff08;通常称为bossGroup&#xff09;&…

【前端】Vue中使用CKeditor作为富文本编辑器

官网https://ckeditor.com/ 此处记录一下我在使用的时候具体初始化的代码。 <template><div><textarea :id"id"></textarea></div> </template><script> export default {name: CkEditor,data: function () {return {id:…

前端面经 websocket

应用层协议&#xff0c;实现一个TCP连接上的全双工通信&#xff0c;实时通讯 之前的实时WEB 实现轮询 增加轮询频率 ws wss 明文版本 和 密文版本 特点 # 1 头部小 2 更注重实时性

【笔记】suna部署之获取 Supabase API key 和 project URL

#工作记录 Supabase | The Open Source Firebase Alternative 一、注册与登录 方式一&#xff1a;GitHub 授权登录 在登录页面选择 “继续使用 GitHub” &#xff0c;跳转到 GitHub 授权页面&#xff08;如图 5 所示&#xff09;。确认 “Supabase 的想要访问您的 [账户名] 帐…

爬虫工具链的详细分类解析

以下是针对爬虫工具链的详细分类解析&#xff0c;涵盖静态页面、动态渲染和框架开发三大场景的技术选型与核心特性&#xff1a; &#x1f9e9; 一、静态页面抓取&#xff08;HTML结构固定&#xff09; 工具组合&#xff1a;Requests BeautifulSoup 适用场景&#xff1a;目标数…

STM32F407寄存器操作(ADC非连续扫描模式)

1.前言 书接上回&#xff0c;在看手册的时候我突然发现手册上还描述了另一种ADC扫描模式&#xff0c;即非连续扫描模式&#xff0c;想着连续扫描模式都已经探索过了&#xff0c;那就顺手把非非连续模式研究一下吧。 2.理论 我们先看看手册&#xff0c;这里我就以规则通道举例…

spring切面

概念 两个特点&#xff1a; IOC控制反转AOP主要用来处理公共的代码 例如一个案例就是添加用户&#xff0c;重复的代码包含了记录日志、事务提交和事务回滚等&#xff0c;都是重复的&#xff0c;为了简单&#xff0c;交给AOP来做。 即将复杂的需求分解出不同方面&#xff0c…

[Python] Python中的多重继承

文章目录 Lora中的例子 Lora中的例子 https://github.com/michaelnny/QLoRA-LLM/blob/main/qlora_llm/models/lora.py#L211C1-L243C10如果继承两个父类&#xff0c;并且父类的__init__参数不一样&#xff0c;则可以显式的调用父类init&#xff1b;如果用super().__init__()则需…

rsync服务的搭建

目录 一、rsync介绍 rsync的安装 二、rsync的语法 三、rsync命令使用 1. 本机同步 2. 远程同步 四、rsync作为服务使用 1、尝试启动rsync程序 2、rsync的配置文件介绍 注意事项&#xff1a; 3. rsyncinotify实时同步 3.依赖服务托管xinetd&#xff08;CentOS 6中rs…

【C/C++】面试基础题目收集

C 软件开发面试中常见的刷题题目通常可分为以下几大类&#xff1a;数据结构与算法、系统编程、面向对象设计、C 语言特性、并发编程等。 &#x1f9e0; 一、数据结构与算法&#xff08;力扣/牛客经典题&#xff09; 掌握 STL 和底层结构实现能力&#xff1a; &#x1f4cc; 数…

将手机网络经USB数据线和本地局域网共享给华为AP6050DN无线接入点

引言 由于最近装毕的新家所在的小区未能及时通宽带,于是家中各类无线设备如何上网就成了首要要解决的问题。 鉴于家中要联网的设备多、类型杂、支持频段也不一,总是开手机热点不是回事儿,于是就想着把手机网络引至华为AP6050DN无线接入点中,让家中所有的无线设备都能快速高…

【数据结构】图论核心算法解析:深度优先搜索(DFS)的纵深遍历与生成树实战指南​

深度优先搜索 导读&#xff1a;从广度到深度&#xff0c;探索图的遍历奥秘一、深度优先搜索二、算法思路三、算法逻辑四、算法评价五、深度优先生成树六、有向图与无向图结语&#xff1a;深潜与回溯&#xff0c;揭开图论世界的另一面 导读&#xff1a;从广度到深度&#xff0c;…

Flink CEP实践总结:使用方法、常见报错、优化与难点应对

Flink CEP实践总结&#xff1a;使用方法、常见报错、优化与难点应对 随着实时数据分析需求的提升&#xff0c;Flink CEP&#xff08;Complex Event Processing&#xff0c;复杂事件处理&#xff09;成为事件流检测中的利器。本文结合实际项目经验&#xff0c;总结Flink CEP的基…

Python数据类型详解:从字符串到布尔值,一网打尽

Python是现代编程语言中非常流行的一种&#xff0c;它的语法简洁、易懂&#xff0c;非常适合初学者。而在Python编程中&#xff0c;“数据类型”是最基础也是最重要的概念。理解这个概念&#xff0c;将为你之后的编程打下坚实的基础。 1. 什么是数据类型&#xff1f; 在Pytho…