算法导论记录丨16.1 活动选择、877. 石子游戏

算法导论_16.1 活动选择(贪心算法) 贪心算法: 最优化问题的算法往往都包含一系列的步骤,每个步骤都要做出最优化的选择(相对全局来说也是最优的); 贪心算法所做的选择看起来是当前最佳的,(相对于局部来讲是最佳的, 相对于全局来讲并不是最佳的),贪心算法希望通过局部的最优解得到一个全局最优解; 注意:贪心算法有时候你能够产生全局最优解,有时候并不能产生全局最优解; 一种称为拟阵的组合结构, 对于这种结构, 贪心算法总是能够给出最优解; 一、活动选择问题 n个活动, S = {a1, a2, …, an}; 每个活动有, 开始时间: s1, s2, 阅读详情

16.1 活动选择

最优子结构

活动选择问题的最优子结构意味着问题的最优解包含了其子问题的最优解。具体来说,如果我们有一个按结束时间排序的活动集合 S={a1​,a2​,...,an​},并且 S’ 是 S 的最大兼容活动子集,那么对于 S′ 中的任何活动aj​,S′ 也包含了在活动aj​ 之前结束的所有活动中的最大兼容子集。

这个属性允许我们使用贪心策略来构建解决方案,因为在选择了当前最优的活动之后,剩余的选择可以独立于已经做出的选择,并且仍然达到最优。

贪心策略

活动选择问题的贪心策略基于一个简单的原则:总是选择结束时间最早的活动,然后从剩余的与已选择活动不冲突的活动中继续应用这一策略。这种方法的有效性在于它能够最大化剩余时间,从而增加选择其他活动的机会。

  1. 排序:首先按照活动的结束时间对活动进行排序。
  2. 选择:选择结束时间最早的活动,并将其加入到最优解集合中。
  3. 剔除:移除与已选择活动时间上冲突的所有活动。
  4. 重复:重复步骤2和3,直到没有更多的活动可以选择。

Python 实现

迭代:
def activity_selection(activities):
    # 按结束时间对活动进行排序
    sorted_activities = sorted(activities, key=lambda x: x[1])
    
    # 选择第一个活动
    n = len(sorted_activities)
    last_selected = 0
    selected_activities = [sorted_activities[0]]
    
    # 遍历剩余的活动
    for i in range(1, n):
        # 如果当前活动的开始时间大于或等于上一个选择的活动的结束时间
        if sorted_activities[i][0] >= sorted_activities[last_selected][1]:
            # 选择当前活动
            selected_activities.append(sorted_activities[i])
            last_selected = i
    
    return selected_activities
递归:
def recursive_activity_selector(s, f, k, n):
    # 查找第一个结束时间在k之后开始的活动
    m = k + 1
    while m <= n and s[m] < f[k]:
        m += 1
    
    if m <= n:
        # 如果找到这样的活动,选择它,并递归地寻找下一个活动
        return [m] + recursive_activity_selector(s, f, m, n)
    else:
        # 如果没有更多活动可以选择,返回空列表
        return []

 877. 石子游戏 感觉被狠狠地耍了!!

class Solution:
    def stoneGame(self, piles: List[int]) -> bool:
        n = len(piles)
        dp = [[0] * n for _ in range(n)]
        for i in range(n):
            dp[i][i] = piles[i]
        for length in range(2, n + 1):
            for start in range(n - length + 1):
                end = start + length - 1
                dp[start][end] = max(piles[start] - dp[start + 1][end], piles[end] - dp[start][end - 1])
        return dp[0][n - 1] > 0

真不看题解很难理解dp数组的定义,已经能够想到pi...pj分选左还是选右了,但是dp定义差值是真想不到。

定义最优子结构

  • 问题的分解:石子游戏可以被分解成一系列更小的子问题,每个子问题都涉及到从一系列石子堆中选择石子的决策。对于任何一对给定的起始和结束点i和j,问题变成了在这个子序列中选择石子以最大化当前玩家相对于对手的分数差。
  • 子问题的最优解:每个子问题的最优解是指在给定的子序列中,玩家可以获得的最大分数差。这个最优解依赖于玩家在子序列的两端选择石子的决策。

最优子结构的体现

  • 当一个玩家面对一个石子堆序列[i...j]时,他们的目标是最大化自己相对于对手的分数差。这个目标可以通过选择序列两端的石子来实现,每次选择后,问题就缩小到一个更小的子序列,要么是[i+1...j],要么是[i...j-1]。
  • 对于每个这样的子序列,玩家都面临着同样的问题:如何选择石子以最大化自己的分数差。因此,大问题的最优解依赖于这些子问题的最优解。

状态转移方程

  • 最优子结构允许我们通过状态转移方程来表达问题的解:dp[i][j] = max(piles[i] - dp[i+1][j], piles[j] - dp[i][j-1])。这个方程说明了当前玩家在子序列[i...j]中的最优选择依赖于在缩小的子序列[i+1...j]和[i...j-1]中的最优选择。

但是实际上对于偶数堆石子的情况,Alice 可以通过选择奇数位置的石子堆或偶数位置的石子堆(从1开始计数)来强迫bob只能选另一种位置的石子堆,确保自己能够获得更多的石子。因为石子总数是奇数,所以奇数位置的石子总数和偶数位置的石子总数不可能相等,Alice 可以选择较多的那一组。

class Solution:
    def stoneGame(self, piles: List[int]) -> bool:
        return True

所以这个问题先手必胜...

也算练习一下dp吧...想休息了...

活动选择(贪心算法基础) 题目如下图所示 代码思路很简单,就是将活动按照结束的时间进行排序,然后找不相交的几个时间段,输出即可。这里只是需要注意一点,就是:结束时间一样的活动按照原来的顺序排序,如果使用选择排序的话,由于选择排序是不稳定的排序,需要添加新的条件。 #include <iostream> using namespace std; struct node { int Id; int Begin; int End; } activity[110], temp; int main() { 阅读详情

相关推荐

5个4000比特大状态置换算法的设计与分析

下面是 5 个概念性、实验性的 4000 位可逆置换设计。它们都保证是双射,但未经过密码分析,不可直接用于生产系统。风格分别覆盖:三维 SPN、Feistel、可逆元胞自动机、ARX、宽轨迹/Keccak 式结构。 这 5 个设计分别代表了 SPN、Feistel、元胞自动机、ARX、宽轨迹 Keccak 五种不同风格,覆盖了主流大状态置换的构造思路。再次强调:它们只是实验性概念,若要用于实际协议,必须经过严格安全性分析。

HuangJinLong2的博客 351

贪心算法——活动选择

贪心算法,选择局部最优解 活动选择问题,每个活动有开始时间s,结束时间f,找到最大兼容活动集。假设f按照大小顺序排好。 每次就从当前结束时间往后选最近的开始时间的活动 #include &lt;iostream&gt; #include &lt;map&gt; #include &lt;vector&gt; using namespace std; //void ActivitySel...

zhangzhi2ma的博客 1177

如何使用AutoDl平台跑自己的模型(纯干货,步骤很详细)

记录我使用AutoDL云服务器来跑自己模型的全过程

qq_45073592的博客 3万+

活动选择(贪心算法) p226

#include #include typedef struct {   int num;   int s;   int f;   int flag; }active; active act[101]; int cmp(const void *a,const void *b) {  if(  ((active*)a)->f==((active*)b)->f )//b后一

558

ATR2660:卫星导航高增益低噪声放大器芯片数据手册

中国BDS(北斗卫星导航系统),美国的GPS,俄罗斯的GLONASS和欧盟的GALILEO导航系统应用而专门设计。芯片支持3.3V至5V宽电源供电。采用2级放大器的结构设计,具有28dB高增益和0.85dB的低噪声系数。支持BDS、GPS、GALILEO、GLONASS等L。典型功率增益:30dB@5V;典型输入P1dB:-18dBm@3.3V;典型工作电流:12.7mA@3.3V;宽供电电压范围:3.3V~5V;典型噪声系数:0.85dB;频段的多个卫星导航系统;ATR2660是一颗。

YHPsophie的博客 561

从零到一:ESP32-P4 PPA加速的配置陷阱与避坑指南

本文详细解析ESP32-P4结合LVGL的PPA硬件加速配置中的常见陷阱,包括内存对齐、缓冲区设置和同步机制等关键问题。提供实用的避坑指南和优化方案,帮助开发者高效启用esp32p4的PPA加速功能,显著提升图形渲染性能。

sky77的博客 396

活动选择

题目描述 学校在最近几天有 n个活动,这些活动都需要使用学校的大礼堂,在同一时间,礼堂只能被一个活动使。由于有些活动时间上有冲突,学校办公室人员只好让一些活动放弃使用礼堂而使用其他教室。 现在给出 n个活动使用礼堂的起始时间 Bi和结束时间 Ei(Bi < Ei),请你帮助办公室人员安排一些活动来使用礼堂,要求安排的活动尽量多。 输入 第一行一个整数 n(n...

weixin_30411239的博客 214

在统信UOS Server 20上踩坑记:手把手教你搞定openGauss 5.0.0企业版安装(附常见报错解决方案)

本文详细记录了在统信UOS Server 20上安装openGauss 5.0企业版的实战经验,包括环境准备、依赖库问题、目录权限、内存参数调优等常见问题的解决方案。通过伪装系统标识、建立软链接、调整内存参数等方法,成功克服国产操作系统与企业级数据库的兼容性挑战,为开发者提供了一份深度排雷指南。

weixin_28698059的博客 264

活动选择问题

关于活动选择问题的贪心算法解决方案,参考自《算法导论》

Hxy_666的博客 1814

从零到一:KUKA机械臂与ROS的工业级通讯协议深度解析

本文深度解析KUKA机械臂与ROS的工业级通讯协议,重点对比EKI与RSI两种核心接口的技术特点与应用场景。详细介绍了网络架构设计、数据包解析机制及ROS-I集成方法,并提供实时性能优化与故障排除策略,为工程师实现高可靠性工业自动化集成提供完整解决方案。

2a4s6d8f0g的博客 296

Anaconda下安装LabelImg

Anaconda下安装LabelImg

LYH8543的博客 756

活动选择问题(贪心)

假设有n个活动,每个活动有一个起始时间和一个结束时间,现在想在一段固定时间内安排最多的活动数。这个问题是典型的贪心问题,我们把所有的活动按结束时间从小到大排序,这样可以知道最小的那个活动a1一定在最优集合里,因为假设最优结构中没有a1,而是它的最小活动为另一个数假设ax,因为a1是所有活动中最小的,所以如果我们把ax换成a1,最优集合里所有的活动还是兼容的,所以a1一定在最优集合中。这样我们只要先

SeasonJoe的博客 1082

Android So加载机制分析----基于Android14源码

本文深入分析Android 14系统中SO(共享库)的两种加载机制:System.loadLibrary()和System.load()。前者通过ClassLoader查找标准路径加载,后者直接加载指定路径的SO文件。文档详细追踪了从Java层到动态链接器的完整加载链路,包括ClassLoader路径查找、JNI桥接、ART虚拟机处理以及底层linker的符号解析和重定位过程。同时还分析了Namespace隔离、JNI_OnLoad机制等核心内容,为开发者提供全面的SO加载技术解析和问题排查指南。

保持专注,保持热爱 350

视频隐私脱敏工程化:CSRT/KCF追踪算法在本地推理中的实现与边界

在短视频内容合规审查中,动态遮挡(Dynamic Masking)是高频且高耗时的环节。传统手动关键帧打码不仅效率低下,且在目标快速移动或遮挡时极易出现遮罩漂移。本文从计算机视觉工程角度,解析基于CSRT与KCF算法的目标追踪方案在视频隐私处理中的技术路径、性能权衡及落地实践。

Mysssone的博客 212

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【算法拾光】链表 哈希表|K个一组翻转链表 + 两数之和

K个一组翻转链表需分段反转,借助哑节点与前驱指针维护连接,避免断链;两数之和利用哈希表实现O(1)查找,空间换时间,高效定位目标组合。前者考察链表指针操作,后者聚焦映射关系构建,均为面试高频题。

wuqingyigexiaoba的博客 314

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

排序算法深度笔记(下):非比较类排序的线性突破与工程边界

排序算法时间复杂度额外空间复杂度稳定性是否基于比较选择排序O(N^2)(O(1))不稳定是冒泡排序O(N^2)(O(1))稳定是插入排序O(N^2)(O(1))稳定是归并排序O(N\log N)(O(N))稳定是快速排序O(N\log N)O(log N)不稳定是堆排序O(N\log N)O(1)不稳定是计数排序(O(N + M))O(M))稳定否基数排序O(N)稳定否桶排序平均O(N) / 最坏O(N^2)

2401_87069538的博客 571

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

算法日常・每日刷题--<动态规划>42

本题为“不相交的线”,与最长公共子序列问题相似。使用动态规划求解:定义 dp[i][j] 表示 nums1[0:i] 与 nums2[0:j] 的最大不相交连线数。若元素相等,则继承左上值加1;否则取上方或左方最大值。最终返回 dp[m][n],即两数组的最大不相交连线数。时间复杂度 O(mn),空间复杂度 O(mn)。

2503_92261635的博客 20

C语言程序设计题|有序数组插入数字冒泡排序

题目要求将一个数插入有序数组末尾,并用冒泡排序实现整体升序。代码先将输入数存入数组最后位置,再通过双重循环进行冒泡排序,每轮将较大元素向后移动,最终输出11个升序元素。该方法虽时间复杂度为O(n²),但符合题目要求,逻辑清晰,适合初学者理解排序原理。

2301_81429079的博客 749

【算法拾光】模拟|外观数列 + 数青蛙

本文总结两道模拟题解法:外观数列通过迭代统计连续数字个数生成下一项,关键在于处理末尾字符;数青蛙则模拟青蛙叫声“croak”状态转移,维护各阶段青蛙数量,记录最大并发数并确保全部完成。共性在于严格遵循流程、细致处理边界与非法情况,锻炼字符串遍历与状态管理能力。

wuqingyigexiaoba的博客 370

牛客周赛165C题(前后缀性质,递推,排序,枚举)

题目大意:给定长度为 `n` 的数组,选择 `k ∈ [1,n]`,将前 `k` 个元素整体翻转,后面的元素不变。要求操作后的整个数组非递减,统计满足条件的 `k` 的数量。题目链接:https://ac.nowcoder.com/acm/contest/141721/C。时间复杂度:O(nlogn)

2501_94316951的博客 170

408 算法 04|主元素与三元组最小距离:两种“扫描时做决定“的思路

2013(41) 的主元素用摩尔投票一遍选出候选,但真正的考点是"选完必须验票";2020(41) 的三元组最小距离,三指针每次只挪最小的那个,靠的是 D=2×(max−min) 这个恒等式。两套完整 C 代码加真实输出,附官方评分档位表。

m0_56226131的博客 409

【数据结构-3】算法美学之降复杂度

在while循环的循环体内,首先用临时变量保存最后一个位置的数据,再通过for循环把所有元素往后移动一位,最后把tmp中保存的值放到下标为0的位置上去。方法二的思路是:创建新数组,让原数组中后k个数据移动到新数组中前面的位置,让原数组中前numsSize-k个数据移动到新数组中后面的位置,这。这段代码的思路是:三次逆置,第一次逆置前numsSize-k个数据,第二次逆置后k个数据,最后整体逆置。这篇博文分享一道解法不一的算法题,求解过程的目的在于降低算法的时间复杂度,题源力扣。,属于空间换时间的操作。

weixin_44218929的博客 85

算法61,判定是否为字符重排

两字符串能互为重排 ⇔。

sheshibenniaodan的博客 218

算法日常・每日刷题--<动态规划>32

给定严格递增的正整数数组,求最长斐波那契子序列长度。使用二维DP,dp[i][j]表示以arr[i]、arr[j]为最后两项的序列长度,初始化均为2。通过哈希表快速查找前一项target = arr[j] - arr[i],若存在且下标小于i,则状态转移:dp[i][j] = dp[k][i] + 1。遍历更新全局最大长度,最终若结果小于3则返回0。时间复杂度O(n²),空间复杂度O(n²)。

2503_92261635的博客 178

算法札记:几何分布在算法题UVA1262的运用

集卡问题求解核心:将集齐n种优惠券的过程分为n个阶段,每个阶段期望购买次数为 $ \frac{n}{k} $(k为剩余种类数),总期望为 $ n \cdot H_n $(调和数)。通过自洽方程推导单阶段期望,无需几何分布或无穷级数,逻辑清晰且适用于大一水平。例如,n=5时期望约11.42,非5。题目要求以带分数形式输出精确结果,算法上需累加分数并化简。

Keven_11的博客 351
上一篇: 算法导论记录丨[重看] 最大子数组、1143. 最长公共子序列/15.4 最长公共子序列
下一篇: 代码随想录算法训练营第三十一天丨455. 分发饼干、376. 摆动序列、53. 最大子数组和
LIEBESFREUD
博客等级 码龄9年 372粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值