【算法】贪心算法(第四章习题解答)

news2024/11/22 11:54:39

4 贪心算法

在这里插入图片描述

4.1

若在 0 − 1 0-1 01 背包问题中, 各物品依重量递增排列时, 其价值恰好依递减序排列. 对于这个特殊的 0 − 1 0-1 01 背包问题, 设计一个有效算法找出最优解, 并说明算法的正确性.

算法设计:由题目所给的信息可以知道这种特殊的背包问题可以通过贪心算法得到最优解。

正确性证明:采用反证法,各物品依重量递增、价值递减序排列时,如果存在其他最优解使得在总限重条件下背包的价值更高,可以分为以下三种情形:

①物品个数比贪心算法得到的解更少,根据题目条件和贪心算法的性质,此情况不可能存在。

②物品个数比贪心算法得到的解相等,由于贪心算法选取的顺序是价值递减的顺序,此情况不存在。

③物品个数比贪心算法得到的解更多,假设存在的最优解与贪心算法的解去掉二者交集后,最优解中还剩两个或两个以上的物品 x j , x k x_j,x_k xj,xk,其总价值大于贪心算法选取的一个物品 x i x_i xi,即 v j + v k > v i v_j+v_k>v_i vj+vk>vi,但是由于 w i < w j < w k w_i<w_j<w_k wi<wj<wk以及 v i > v j > v k v_i>v_j>v_k vi>vj>vk因此一定有 v j + v k < v i + v j v_j+v_k<v_i+v_j vj+vk<vi+vj,与贪心算法的机制违背,此情况不成立。

综上所述,贪心算法可以找到此问题的最优解。

数据输入:物品重量数组 W [ 1.. n ] W[1..n] W[1..n],物品价值数组 V [ 1.. n ] V[1..n] V[1..n],背包限重 w w w

结果输出:布尔类型数组 O [ 1.. n ] O[1..n] O[1..n],值为 T r u e True True代表相应的物品装入背包,反之 F a l s e False False为放弃该物品。

伪码描述:

  1. O [ 1.. n ] ← { F a l s e , F a l s e . . . F a l s e } O[1..n]\leftarrow\{False,False...False\} O[1..n]{False,False...False}
  2. w e i g h t ← 0 weight\leftarrow0 weight0
  3. i ← 1 i\leftarrow1 i1
  4. w h i l e    T r u e    d o while\ \ True\ \ do while  True  do
  5. i f    w e i g h t + W [ i ] ≤ w / / 验证能否放入背包 if \ \ weight+W[i]≤w\quad//验证能否放入背包 if  weight+W[i]w//验证能否放入背包
  6. t h e n    O [ i ] = T r u e ;   i = i + 1 / / 放入背包并进入下一次循环 then\ \ O[i]=True;\ i=i+1\quad//放入背包并进入下一次循环 then  O[i]=True; i=i+1//放入背包并进入下一次循环
  7. e l s e    r e t u r n    O [ 1.. n ] else\ \ return\ \ O[1..n] else  return  O[1..n]

复杂度分析:该算法使用贪心算法,时间复杂度随输入规模一次线性增长,因此易得算法的时间复杂度是
W ( n ) = O ( n ) \begin{aligned} W(n)=O( n ) \end{aligned} W(n)=O(n)
算法需要一个布尔类型数组 O [ 1.. n ] O[1..n] O[1..n]来记录背包放入情况,因此空间复杂度是
S ( n ) = O ( n ) \begin{aligned} S(n)=O(n ) \end{aligned} S(n)=O(n)

4.2

将最优装载问题的贪心算法推广到两艘船的情形, 贪心算法仍然能产生最优解么? 若能, 给出证明. 若不能, 请给出反例.

证明:

如果使用贪心算法求解,必须把第一艘尽可能的装满,才能使总的装载量更多,第一艘船装载的方式只可能有一种最优解,即装载的物品都是以从轻到重的顺序装载,但是这样装并不一定得到最优解,例如下面这个例子:

假设${w_1,w_2,w_3,w_4,w_5}={10,20,30,40,50},c_1=50,c_2=50 ,贪心算法得到的解为 ,贪心算法得到的解为 ,贪心算法得到的解为{10,20},{30} ,这很显然不是最优解,最优解为 ,这很显然不是最优解,最优解为 ,这很显然不是最优解,最优解为{10,40},{20,30}$。

综上所述,将最优装载问题的贪心算法推广到两艘船的情形,贪心算法并不能保证产生最优解,该问题可以采用回溯法或动态规划等其他方法解决得到最优解。

4.3

Γ = 1 , . . . , n Γ = {1, . . . , n} Γ=1,...,n n n n 个字符的集合. 证明关于 Γ Γ Γ 的任何最优前缀码可以表示长度为 2 n − 1 + n ⌈ l o g n ⌉ 2n − 1 + n⌈log n⌉ 2n1+nlogn 位的编码序列. (提示: 先考虑树结构的编码, 再考虑叶结点对应字符的编码)

证明:

最优前缀编码所对应的编码二叉树是一棵完全二叉树,有 n n n个叶节点和 n − 1 n-1 n1个内节点,叶节点和内节点需要用 0 − 1 0-1 01区分,并通过对编码树前序遍历的结果来唯一确定编码树的结构,这个前序遍历结果有 2 n − 1 2n-1 2n1位。

叶节点所携带的数据使用二进制编码表示,因此每个叶节点需要 ⌈ l o g n ⌉ ⌈log n⌉ logn位编码,有 n n n个叶节点,因此共需要 n ⌈ l o g n ⌉ n⌈log n⌉ nlogn位编码来表示叶节点携带的数据。

综上,关于 Γ Γ Γ 的任何最优前缀码可以表示长度为 2 n − 1 + n ⌈ l o g n ⌉ 2n − 1 + n⌈log n⌉ 2n1+nlogn 位的编码序列。

4.4

给定 x x x 轴上 n n n 个闭区间. 去掉尽可能少的闭区间, 使得剩下的闭区间都不相交. 设计一个有效算法找出最优解, 并说明算法的正确性.

算法设计:首先对所有区间按照右端点升序的顺序进行排序,然后在排序后的结果中统计不相交的区间个数,最后将总区间个数减去不相交的区间个数计算出需删掉的区间个数。

正确性证明:由于首先对所有区间按照右端点升序的顺序进行了排序,需要尽可能保留更多的区间,因此这个问题就可以转化为 4.1 4.1 4.1中的特殊 0 − 1 0-1 01背包问题,具体证明不再赘述,详见 4.1 4.1 4.1

数据输入:闭区间个数 n n n n n n个闭区间组成的数组 x [ n ] [ 2 ] x[n][2] x[n][2]

结果输出:需要去掉的尽可能少的闭区间数 c u t N u m b e r cutNumber cutNumber

伪码描述:

  1. x ← Sort ⁡ ( x ) / / 首先对所有区间按照右端点升序的顺序进行排序 x \leftarrow \operatorname{Sort}(x) \quad / /首先对所有区间按照右端点升序的顺序进行排序 xSort(x)//首先对所有区间按照右端点升序的顺序进行排序
  2. c u t N u m b e r ← 0 / / 需要去掉的尽可能少的闭区间数 cutNumber\leftarrow0\quad//需要去掉的尽可能少的闭区间数 cutNumber0//需要去掉的尽可能少的闭区间数
  3. c u r v e ← 1 curve\leftarrow1 curve1
  4. f o r    i ← 2    t o    n    d o / / 遍历所有区间 for \ \ i \leftarrow 2 \ \ to \ \ n \ \ do\quad//遍历所有区间 for  i2  to  n  do//遍历所有区间
  5. i f    x [ i ] [ 1 ] ≥ x [ c u r v e ] [ 2 ] / / 验证区间是否重合 if \ \ x[i][1]≥x[curve][2]\quad//验证区间是否重合 if  x[i][1]x[curve][2]//验证区间是否重合
  6. t h e n    c u r v e = i / / 没有重合 then\ \ curve=i\quad//没有重合 then  curve=i//没有重合
  7. e l s e    c u t N u m b e r = c u t N u m b e r + 1 / / 存在重合,需要去掉 else\ \ cutNumber=cutNumber+1\quad//存在重合,需要去掉 else  cutNumber=cutNumber+1//存在重合,需要去掉
  8. r e t u r n    c u t N u m b e r return\ \ cutNumber return  cutNumber

复杂度分析:该算法使用贪心算法,时间复杂度随输入规模一次线性增长,因此易得算法的时间复杂度是
W ( n ) = O ( n ) \begin{aligned} W(n)=O( n ) \end{aligned} W(n)=O(n)
默认排序算法都在原数组上完成,因此算法只需要常数规模的存储空间,空间复杂度是
S ( n ) = O ( 1 ) \begin{aligned} S(n)=O(1 ) \end{aligned} S(n)=O(1)

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

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

相关文章

基于多保真方法来估计方差和全局敏感度指数分析(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 此代码实现了多保真方法来估计方差和全局敏感度指数。当模型具有不确定的输入时&#xff0c;模型输出也是不确定的。基于方差的…

C++与QML混合编程

一、前言 简单来说&#xff0c;混合编程就是通过Qml高效便捷的构建UI界面&#xff0c;而使用C 来实现业务逻辑和复杂算法。Qt集成了QML引擎和Qt元对象系统&#xff0c;使得QML很容易从C 中得到扩展&#xff0c;在一定的条件下&#xff0c;QML就可以访问QObject派生类的成员&am…

112.(leaflet之家)leaflet椭圆修改

听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 下面献上完整代码,代码重要位置会做相应解释 <!DOCTYPE html> <html>

OpenHarmony之轻量系统编译构建流程

首先我们先来熟悉几个概念&#xff1a; - 子系统 子系统是一个逻辑概念&#xff0c;它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计&#xff0c;从下向上依次为&#xff1a;内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 组件”逐级…

别人家的公司年终奖52个月工资-互联网企业年终裁员脸在哪

52个月工资&#xff0c;开玩笑吧&#xff0c;还真不是。据台湾媒体报道&#xff0c;中国台湾长荣海运年终奖出炉&#xff0c;继去年40个月年终奖后&#xff0c;今年再创新高&#xff0c;传言最高发放52个月年终奖金。以基层员工月薪5万新台币计算&#xff0c;表现好的员工可领到…

6.vector、set和map

一、vector 1.简介 有些时候想开一个数组&#xff0c;但是却不知道应该开多大长度的数组合适&#xff0c;因为我们需要用到的数组可能会根据情况变动。这时候我们就需要用到动态数组。 所谓动态数组&#xff0c;也就是不定长数组&#xff0c;数组的长度是可以根据我们的需要…

第四章快速排序——分而治之

分而治之&#xff08;divide and conquer,D&C&#xff09; D&C算法是递归的&#xff0c;并且有2个步骤&#xff1a; 找出基线条件&#xff0c;并且条件尽可能简单不断将问题分解&#xff0c;直到符合基线条件 给定一个数组&#xff0c;求和&#xff1a; 利用循环很容…

秒懂双向链表

目录 一、双向链表概述 二、模拟实现双向链表 1、头插法插入元素 2、尾插法插入元素 3、在指定位置插入元素 4、查询双向链表中是否包含key 5、删除第一次出现关键字为key的结点 6、删除所有值为key的结点 7、求双向链表的长度 8、遍历双向链表 9、清空双向链表 三…

【 uniapp - 黑马优购 | 商品列表 】如何实现数据获取、结构渲染、自定义组件的封装

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;讨厌编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;小新爱学习. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc…

在 Mac 上将 PDF 转换为 Word 的 5 种简单方法

当谈到将PDF格式转换为Word格式时&#xff0c;用户可能会从互联网上搜索并尝试在线将PDF转换为Word。如果是这样&#xff0c;您可能会得到不好的结果并冒着文件本身的风险。在线 PDF 到 Word 转换器工具可能会产生低质量的输出&#xff0c;对文件大小有限制&#xff0c;更糟糕的…

maven多模块依赖版本不一致问题

项目结构&#xff1a; ├─springcloud-alibaba ├─.idea├─shop-common├─shop-order├─shop-product└─shop-user项目环境&#xff1a; 父工程&#xff1a; <properties><spring-cloud.version>Greenwich.RELEASE</spring-cloud.version><sprin…

java虚拟机之垃圾回收机制

一.需要回收的内存区域 程序计数器、虚拟机栈、本地方法栈 3 个区域随线程生灭(因为是线程私有)&#xff0c;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。而 Java 堆和方法区则不一样&#xff0c;一个接口中的多个实现类需要的内存可能不一样&#xff0c…

<Focal Loss for Dense Object Detection>论文解读

目录1.简介2.模型2.1 二阶段要比单阶段模型效果好本质原因2.2 模型结构2.3.focal loss2.3.1 公式说明2.3.2 其他2.4 消融实验3.源码详解1.简介 目标识别有两大经典结构: 第一类是以Faster RCNN为代表的二阶段识别方法&#xff0c;这种结构的第一阶段专注于proposal的提取&am…

后端开发规约

目录 项目MVC层级设计规范 工程项目模块设计 设计规约 Java编码规范 参考《阿里巴巴Java开发手册》&#xff0c;见文末参考文档 OOP 面向对象设计 & 面向接口编程 Lombok工具包依赖 Guava、Hutool 等脚手架工具包&#xff08;三方包使用其一即可&#xff09; 日志打…

python初级教程十 Mongodb增、删、改、查

Mongodb 插入文档 MongoDB 中的一个文档类似 SQL 表中的一条记录。 插入集合 集合中插入文档使用 insert_one() 方法&#xff0c;该方法的第一参数是字典 name > value 对。 以下实例向 sites 集合中插入文档&#xff1a; #!/usr/bin/python3import pymongomyclient p…

03、Java并发 Java 线程池 ( Thread Pool ) (上)

本文我们将讲解 Java 中的线程池 ( Thread Pool )&#xff0c;从 Java 标准库中的线程池的不同实现开始&#xff0c;到 Google 开发的 Guava 库的前世今生。 本章节涉及到很多前几个章节中阐述的知识点。我们希望你是按照顺序阅读下来的&#xff0c;不然有些知识会一头雾水。 J…

Redis基础篇——Redis安装以及配置文件的修改

文章目录1. 认识Redis1.1 特征1.2 安装 Redis1. 安装 Redis 依赖2. 上传安装包1.3 默认启动1.4 指定配置启动1.5 开机自启&#xff08;推荐&#xff09;1. 认识Redis Redis 诞生于 2009 年&#xff0c;全称是 Remote Dictionary Server&#xff0c;远程词典服务器&#xff0c;…

Databend 开源周报 #73

Databend 是一款强大的云数仓。专为弹性和高效设计&#xff0c;自由且开源。 即刻体验云服务&#xff1a;https://app.databend.com。 What’s New 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 Features & Improvements Multiple Catalogs …

hudi实战-- 核心点解析

目录 Hudi 基础功能 Hudi 简介 Hudi 功能 Hudi 的特性 Hudi 的 架构 Hudi 数据管理 Hudi 表数据结构 hoodie 文件 数据文件 数据存储概述 Metadata 元数据 Index 索引 索引策略 Data 数据 Hudi 核心点解析 基本概念 时间轴Timeline 文件管理 索引 Index 表的存储…

NiN详解

入门小菜鸟&#xff0c;希望像做笔记记录自己学的东西&#xff0c;也希望能帮助到同样入门的人&#xff0c;更希望大佬们帮忙纠错啦~侵权立删。 ✨完整代码在我的github上&#xff0c;有需要的朋友可以康康✨ https://github.com/tt-s-t/Deep-Learning.git 目录 一、NiN网络的…