贪心算法概述

贪心算法总是作出当前看来最好的选择,是局部最优

可以使用贪心算法的问题一般具有两个重要的性质

  • 贪心选择性质
  • 最优子结构性质

贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择来达到

其与动态规划的问题区别在于,动态规划算法通常以自底向上的方式解决子问题,贪心为自顶向下的方式进行。

最优子结构性质

一个问题的最优解包含其子问题的最优解

1.活动安排问题

设有n个活动的集合E={1,2,…,n},其中每个活动都 要求使用同一资源,如演讲会场等,而在同一时间内只有 一个活动能使用这一资源。每个活动i都有一个要求使用 该资源的起始时间si和一个结束时间fi,且si<fi。如果选 择了活动i,则它在半开时间区间[si, fi)内占用资源。若 区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是 相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相 容。

template<class Type>//s为每个活动的开始时间,f为结束时间(按结束时间的非减
序排列),集合A中存放执行的活动
void GreedySelector(int n,Type s[],Type f[],bool A[])
{
    A[1] = true;
    int j = 1;
    for(int i = 2;i<=n;i++){
        if(s[i]>=f[j]) {A[i] = true;j = i;}
        else A[i] = false;
    }
}

每次总是选择具有最早完成时间的 相容活动加入集合A中。

该算法的贪心选择的意义是使剩余的可安排时间段极大 化,以便安排尽可能多的相容活动。

当输入的活动已 按结束时间的非减序排列,算法只需O(n)的时间安排n个 活动,使最多的活动能相容地使用公共资源。如果所给 出的活动未按非减序排列,可以用O(nlogn)的时间重排。

2.背包问题

0-1背包问题

给定n种物品和一个背包。物品i的重量是Wi,其价值 为Vi,背包的容量为C。应如何选择装入背包的物品, 使得装入背包中物品的总价值最大?

note:0-1背包问题不能将物品i装入背包多次,也不能只装入 部分的物品i。

背包问题

与0-1背包问题类似,所不同的是在选择物品i装入 背包时,可以选择物品i的一部分,而不一定要全部装 入背包,1≤i≤n。

背包问题可以用贪心算法求解,而0-1背包问题却不可以用贪心算法求解

基本步骤为计算每种物品单位重量的价值,然后依照贪心选择策略,将尽可能多的单位重量价值最高的物品放到背包中,直到背包装满为止

void Knapsack(int n,float M,float v[],float w[],float x[])
{//v价值,w质量,n为物品数量
    Sort(n,v,w);//这时的w已经按照单位价值排序完成
    int i;
    for (i=1;i<=n;i++) x[i]=0;
    float c=M;//c表示当前剩余背包容量
    for (i=1;i<=n;i++) {
        if (w[i]>c) break;
        x[i]=1;
        c-=w[i];
    }
    if (i<=n) x[i]=c/w[i];//剩余容量除以w[i],得到使用w[i]多少    
}

3.最优装载问题

有一批集装箱要装上一艘载重量为c的轮船。其中 集装箱i的重量为Wi。最优装载问题要求确定在装载体 积不受限制的情况下,将尽可能多的集装箱装上轮船,且要输出所选集装箱编号。

采用重量最轻者先 装的贪心选择策略

template<class Type>
void Loading(int x[], Type w[], float c, int n)
{
    int *t = new int [n+1]; //按照集装箱重量从轻到重的顺序
    SelectSort(w, t, n);//不使用质量直接排序,要确定每个集装箱对应序号
    //w[t[i]]代表序号为t[i]的质量,而t[i]是按照集装箱重量从轻到重的顺序
    for (int i = 1; i <= n; i++) x[i] = 0;//x表示时候被选择
    for (int i = 1; i <= n && w[t[i]] <= c; i++)
    {x[t[i]] = 1; c -= w[t[i]];}
}

template<class Type>
void SelectSort(Type w[],int *t,int n)
{
    Type tempArray[n+1],temp;//将w拷贝到临时数组tempArray中
    memcpy(tempArray,w,(n+1)*sizeof(Type));
    int min;
    for(int i=1;i<=n;i++) t[i] = i;
    //下面为选择排序
    for(int i=1;i<n;i++)
    {
        min=i;
        for(int j=i+1;j<=n;j++)
        {
            if(tempArray[min]>tempArray[j])
                min=j;           
        }
        Swap(tempArray[i],tempArray[min]);
        Swap(t[i],t[min]);

    }
}

note:由于需要进行排序,故算法所需时间复杂度为O(nlogn),这里不明白的可参考我的文章算法分析与设计(研)

4.哈夫曼编码

哈夫曼编码是广泛地用于数据文件压缩的 十分有效的编码方法。

其思想: 给出现频率高的字符较短的编码,出现频率较 低的字符以较长的编码,可以大大缩短总码长

例子:给出如下字符与出现频率

对于定长码,给每个字符分配固定长度的编码,而变长码则是根据出现频率构造一棵树,小的频率放在左边,用0代表,大的频率放在右面,用1代表 

对每一个字符规定一个0,1串作为其代码,并要求任一 字符的代码都不是其它字符代码的前缀。这种编码称 为前缀码。

表示最优前缀码的二叉树总是一棵完全二叉树,即树中任一结点都有2个儿子结点。

 哈夫曼提出构造最优前缀码的贪心算法,由此产 生的编码方案称为哈夫曼编码。

算法以|C|个叶结点开始,执行|C|-1次的“合并” 运算后产生最终所要求的树T。

在算法huffmanTree中,编码字符集中每一字符c 的频率是f(c)。以f为键值的优先队列Q用在贪心选择时 有效地确定算法当前要合并的2棵具有最小频率的树。 一旦2棵具有最小频率的树合并后,产生一棵新的树, 其频率为合并的2棵树的频率之和,并将新树插入优先 队列Q。经过n-1次的合并后,优先队列中只剩下一 棵树,即所要求的树T。

关于n个字 符的哈夫曼算法的计算时间为O(nlogn) 。

5.单源最短路径

给定带权有向图G =(V,E),其中每条边的权是非负 实数。另外,还给定V中的一个顶点,称为源。现在要 计算从源到所有其它各顶点的最短路径长度。这里路 的长度是指路上各边权之和。这个问题通常称为单源 最短路径问题。

Dijkstra算法是解单源最短路径问题的贪心算法。

其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集 合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。

步骤:

  1. 初始时,S中仅含有源。
  2. 设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为 从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短 特殊路径长度。
  3. Dijkstra算法:每次从V-S中取出具有最短特殊路长度的顶点u,将 u添加到S中,同时对数组dist作必要的修改。 当S添加u之后,可能出现一条到顶点的新的特殊路,如果这条新特 殊路是先经过老的S到达顶点u,然后从u经过一条边直接到达顶点i, 则这种路的最短长度是dist[u]+c[u][i]。如果 dist[u]+c[u][i] < dist[i] 则需要更新dist[i]的值,并且将u赋值给prev[i]。
  4. 当S包含了所有V中顶点,dist就记录了从源到所有其它顶点之 间的最短路径长度。

直观来说,每次选择未被加入的距离最短的点加入S,加入后重新调整S到各点的距离

dist[u]+c[u][i] < dist[i],这个公式的意思是,从源到u的距离加上u到i的距离小于源到i的距离

prev数组代表到达该点的前一个点是什么

证明:

最优子结构性质

贪心性质

从V-S中选择具有最短特殊路径的顶点u,从而确定从源 到u的最短路径长度dist[u]。为什么从源到u没有更短 的其他路径?

只管看来就是如果有更短的路径d(v,x)+d(v,u)  = d(v,u),那么很明显dist[x]更短,我们没有选择,那么就是与贪心选择矛盾 

时间复杂度为O(n^2),原因在于每次选择为O(n),然后需要选择n-1次

6.最小生成树

设G =(V,E)是无向连通带权图,即一个网络。E中 每条边(v,w)的权为c[v][w]。如果G的子图G’是一棵包 含G的所有顶点的树,则称G’为G的生成树。生成树上 各边权的总和称为该生成树的耗费。在G的所有生成树 中,耗费最小的生成树称为G的最小生成树。

概况来说就是找一个权值和最小的子树

设G=(V,E)是连通带权图,U是V的真子集。如果 (u,v)∈E,且u∈U,v∈V-U,且在所有这样的边中, (u,v)的权c[u][v]最小,那么一定存在G的一棵最小生成 树,它以(u,v)为其中一条边。这个性质有时也称为 MST性质。

解释一下就是最小生成树就是不断选择最小权值的边构成的,这里不可以选择已经包含点之间的连接,需要在未包含的点中和以包含的点中选择

note:E为边集合,V为点集合

Prim算法

构造G的最小生成树的Prim算法的基本思想是: 首先置S={1},然后,只要S是V的真子集,就作如下 的贪心选择:选取满足条件i∈S,j∈V-S,且c[i][j]最小 的边,将顶点j添加到S中。这个过程一直进行到S=V 时为止。

例子

 不断选择权值最小的边来连接新的顶点

 计算时间为O(n^2),找到最小的边需要O(n),而需要进行n-1次

Kruskal算法

首先将G的n个顶点看成n个孤立的连通分支。将所有 的边按权从小到大排序。然后从第一条边开始,依边 权递增的顺序查看每一条边,并按下述方法连接2个不 同的连通分支:

(1)当查看到第k条边(v,w)时,如果端点v和w分别是 当前2个不同的连通分支T1和T2中的顶点时,就用边 (v,w)将T1和T2连接成一个连通分支,然后继续查看第 k+1条边;

(2)如果端点v和w在当前的同一个连通分支中,就直 接再查看第k+1条边。这个过程一直进行到只剩下一 个连通分支时为止。

这个解释来说就是将所有边那权值排序,然后不断加入权值最小的边,这个加入的边要求两边的点至少有一个没有加入S中

当边数为e的时候,时间复杂度为O(eloge)就是排序的时间

7.多机调度问题

多机调度问题要求给出一种作业调度方案,使所 给的n个作业在尽可能短的时间内由m台机器加工处理 完成。

采用最长处理时间作业优先的贪心选择策略可以 设计出解多机调度问题的较好的近似算法。

8.贪心算法的理论基础

借助于拟阵工具,建立关于贪心算法的较为一般的理论,这一理论用于确定什么时候使用贪心算法可以得到整体最优解

拟阵M定义为满足下面3个条件的有序对(S,I):

  1. S是非空有限集。
  2. I是S的一类具有遗传性质的独立子集族,即若B∈I, 则B是S的独立子集,且B的任意子集也都是S的独立子集。空集必为I的成员。
  3. I满足交换性质,即若A∈I,B∈I且|A|<|B|,则存在某 一元素x∈B-A,使得A∪{x}∈I。此时的x称为可扩展元素

在图论中,独立子集(或独立集,Independent Set)是指一个图中这样一组顶点:

  • 这些顶点之间没有边相连
  • 换句话说,图中任意两个属于独立子集的顶点之间都不是邻居。

当拟阵M中的独立子集A没有可扩展元素时,称A 为极大独立子集。

定理1:拟阵中的所有极大独立子集大小相同

许多用贪心算法求解的问题可以表示为求带权拟阵的最大权独立子集问题

给定带权拟阵M=(S,I),确定S的独立子集A∈I使得 W(A)达到最大。这种使W(A)最大的独立子集A称为拟 阵M的最优子集。由于S中任一元素x的权W(x)是正的, 因此,最优子集也一定是极大独立子集。

带权拟阵最优子集算法

每次选择当前能加入到最大权值点加入到A中,时间复杂度为

引理1:设M=(S,I)是拟阵。若S中元素x不是空集 的可扩展元素,则x也不可能是S中任一独立子集A的 可扩展元素。

引理2:拟阵的最优子结构性质

任务时间表问题

给定一个单位时间任务的有限集S。关于S的一 个时间表用于描述S中单位时间任务的执行次序。 时间表中第1个任务从时间0开始执行直至时间1结 束,第2个任务从时间1开始执行至时间2结束,…, 第n个任务从时间n-1开始执行直至时间n结束。

这个问题借助于拟阵可以很好的求解

对于一个给定的S的时间表,在截止时间之前完成 的任务称为及时任务,在截止时间之后完成的任务称 为误时任务。

S的任一时间表可以调整成及时优先形式,即其中 所有及时任务先于误时任务,而不影响原时间表中各 任务的及时或误时性质。还可将S的任一时间表调整成为规范形式, 其中及时任务先于误时任务,且及时任务依其截止时 间的非减序排列。

首先可将时间表调整为及时优先形式,然后再进 一步调整及时任务的次序。

任务时间表问题等价于确定最优时间表中及时任 务子集A的问题。一旦确定了及时任务子集A,将A中 各任务依其截止时间的非减序列出,然后再以任意次 序列出误时任务,即S-A中各任务,由此产生S的一个 规范的最优时间表。

对时间t=1,2,…,n,设Nt (A)是任务子集A中所有 截止时间是t或更早的任务数。考察任务子集A的独立 性。

对于S的任一任务子集A,下面的各命题是 等价的。

任务时间表问题要求使总误时惩罚达到最小,这 等价于使任务时间表中的及时任务的惩罚值之和达到 最大。下面的定理表明可用带权拟阵的贪心算法解任 务时间表问题。

定理2:设S是带有截止时间的单位时间任务集,I 是S的所有独立任务子集构成的集合。则有序对(S,I)是拟 阵。

用带权拟阵的贪心算法可以求得最 大权(惩罚)独立任务子集A,以A作为最优时间表中的及 时任务子集,容易构造最优时间表。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Git 下载问题及解决方法

在某些网络环境下&#xff0c;可能会遇到 Git 无法下载的问题&#xff0c;通常是由于网络限制或需要通过代理访问导致的。以下是常见的解决方法&#xff0c;包括设置代理、取消代理以及其他诊断方法。 1. 设置 Git 代理 在一些网络环境下&#xff0c;可能会使用工具&#xff0…

【算法刷题】数组篇

文章目录 数组中两个数的最⼤异或值找出所有⼦集的异或总和再求和 数组中两个数的最⼤异或值 leet code&#xff1a;https://leetcode.cn/problems/maximum-xor-of-two-numbers-in-an-array/description/暴力解法&#xff1a;【部分样例超时&#xff0c;通过不了&#xff0c;不…

硬件设计-关于ADS54J60的校准问题

目录 简介: 校准模分析: 交错的优势 交错挑战 S/2 fIN处产生杂散。失调不匹配杂散很容易识别,因为只有它位于fS/2处,并可轻松地进行补偿。增益、时序和带宽不匹配都会在输出频谱的fS/2 fIN 处产生杂散;因此,随之而来的问题是:如何确定它们各自的影响。图8以简单的…

python小项目:给复制出来的段落前添加星号

给复制出来的段落前添加星号 最终效果二、实现步骤2.1 编写python脚本2.2 批处理脚本2.3 运行脚本 三、用到知识3.1 pyperclip 模块 最终效果 说明&#xff1a;复制四段内容&#xff08;段落实际不做限制&#xff09;&#xff0c;在windows终端输入 bulletPointAdder&#xff0…

超声波信号采集传感器模块测试分析总结

一 概述 数字化和小型化是目前医学超声的主要发展趋势之一。传统的推车式、大探头超声设备体积巨大且价格昂贵&#xff0c;而现在市场中的小型化超声设备经过更新发展&#xff0c;在保证图像清晰和高分辨率的同时&#xff0c;不仅功能更完善、探头也更多样化。这些新型的小型设…

ArcGIS计算矢量要素集中每一个面的遥感影像平均值、最大值等统计指标

本文介绍在ArcMap软件中&#xff0c;基于矢量面要素集&#xff0c;计算在其中每一个面区域内&#xff0c;遥感影像的像元个数、平均值、总和等统计值&#xff0c;并将统计信息附加到矢量图层的属性表中的方法。 首先&#xff0c;明确一下本文的需求。现在有一个矢量面要素集&am…

AI大模型系列之七:Transformer架构讲解

目录 Transformer网络是什么&#xff1f; 输入模块结构&#xff1a; 编码器模块结构&#xff1a; 解码器模块: 输出模块结构&#xff1a; Transformer 具体是如何工作的&#xff1f; Transformer核心思想是什么&#xff1f; Transformer的代码架构 自注意力机制是什么…

家政预约小程序05活动管理

目录 1 搭建活动管理页面2 搭建活动规则页面3 搭建规则新增页面3 配置规则跳转4 搭建活动参与记录总结 上一篇我们介绍了活动管理的表结构设计&#xff0c;本篇我们介绍一下后台功能。 1 搭建活动管理页面 我们一共搭建了三个表&#xff0c;先搭建主表的后台功能。打开我们的后…

SpringCloud(二)--SpringCloud服务注册与发现

一. 引言 ​ 前文简单介绍了SpringCloud的基本简介与特征&#xff0c;接下来介绍每个组成部分的功能以及经常使用的中间件。本文仅为学习所用&#xff0c;联系侵删。 二. SpringCloud概述 2.1 定义 ​ Spring Cloud是一系列框架的有序集合&#xff0c;它巧妙地利用了Spring…

当生成式AI遇见数字孪生

吴付标 总部位于美国宾夕法尼亚州的Bentley软件公司&#xff0c;于金秋十月在枫叶之国加拿大名城温哥华举办一年一度的2024纵览基础设施大会暨光辉大奖赛。此次盛会吸引了来自全球的数百位行业精英&#xff0c;旨在探讨基础设施数智化的最新趋势&#xff0c;分享生态圈的创新成…

散度与旋度的探讨

一、散度的定义与物理意义 1. 散度的定义 散度(Divergence)是向量分析中的一个核心概念,用于描述一个向量场在某一点的源或汇的强度。在数学上,散度通常使用符号“div”表示。对于一个三维向量场F(x, y, z) = (Fx, Fy, Fz),其散度可以定义为: div F = ∂Fx/∂x + ∂Fy/…

英文字体:创意前卫杀手级标题海报封面设计粗体字体 Morne Display

看啊&#xff0c;设计师们&#xff01;Morne 刚刚进入字体游戏&#xff0c;让我们告诉你&#xff0c;它不是来玩的——认识我们的字体&#xff0c;它就像你早上的咖啡一样大胆。无论您是在制作杀手级标题、偷偷摸摸的副标题还是大胆的海报&#xff0c;Morne 都能为您提供前后、…

LLM - 使用 LLaMA-Factory 部署大模型 HTTP 多模态服务 (4)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/144881432 大模型的 HTTP 服务&#xff0c;通过网络接口&#xff0c;提供 AI 模型功能的服务&#xff0c;允许通过发送 HTTP 请求&#xff0c;交互…

【大模型系列】Mobile-Agent(2024.04)

Paper: https://arxiv.org/pdf/2401.16158Github: https://github.com/X-PLUG/MobileAgentAuthor: Junyang Wang et al. 北交、阿里巴巴 Mobile-agent核心工作&#xff1a; 首先使用视觉感知工具(检测和OCR模型)识别前端界面中文本和图像元素的精确位置 检测图标&#xff1a;…

JVM实战—8.如何分析jstat统计来定位GC

大纲 1.使用jstat了解线上系统的JVM运行状况 2.使用jmap和jhat了解线上系统的对象分布 3.如何分析JVM运行状况并合理优化 4.使用jstat分析模拟的BI系统JVM运行情况 5.使用jstat分析模拟的计算系统JVM运行情况 6.问题汇总 1.使用jstat了解线上系统的JVM运行状况 (1)JVM的…

什么是Redis哨兵机制?

大家好&#xff0c;我是锋哥。今天分享关于【什么是Redis哨兵机制&#xff1f;】面试题。希望对大家有帮助&#xff1b; 什么是Redis哨兵机制&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Redis 哨兵&#xff08;Sentinel&#xff09;机制是 Redis 提…

深度学习的魔法世界

技术文章&#xff1a;深度学习的魔法世界 引言 嘿&#xff0c;今天我们要一起探索一个非常酷的魔法世界——深度学习&#xff01;这是一门让计算机变得超级聪明的科学。我们会用最简单的语言来解释深度学习的基本概念&#xff0c;让你们也能轻松理解。 一、深度学习的六大魔…

数据挖掘——决策树分类

数据挖掘——决策树分类 决策树分类Hunt算法信息增益增益比率基尼指数连续数据总结 决策树分类 树状结构&#xff0c;可以很好的对数据进行分类&#xff1b; 决策树的根节点到叶节点的每一条路径构建一条规则&#xff1b;具有互斥且完备的特点&#xff0c;即每一个样本均被且…

RFID手持机与RFID工业平板在仓储物流管理系统中的选型

概述 随着物联网技术在仓储物流管理系统中的普及&#xff0c;RFID手持机与RFID工业平板作为基于RFID技术手持式读写器的两种重要终端设备形态&#xff0c;得到了广泛应用。尽管RFID手持机与RFID工业平板都具备读写 RFID标签的基本功能&#xff0c;使用场景较为类似&#xff0c…

文件本地和OSS上传

这里写目录标题 前端传出文件后端本地存储阿里云OSS存储上传Demo实现上传ConfigurationProperties 前端传出文件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>上传文件</title> </head&g…