4-1 活动安排问题

news2024/11/26 14:35:04

 

 

 1.什么是贪心算法

 我的理解:

贪心算法是一种常用的问题求解方法,它在每个步骤上都选择当前看起来最优的解,而不考虑整体的最优解。简单来说,贪心算法采取局部最优的决策,希望通过每个局部最优解的选择,最终得到全局最优解。

贪心算法的基本思想是通过贪心选择策略,一步一步地构建解决方案,每次选择都是基于当前情况下的最优决策。它通常适用于满足最优子结构的问题,即一个问题的最优解可以通过子问题的最优解来构建。

然而,需要注意的是,贪心算法并不是适用于所有问题的通用解决方案。有时候贪心选择并不能保证得到全局最优解,可能会导致局部最优解并不是整体最优解的情况。在使用贪心算法时,需要仔细分析问题的特性,确保贪心选择的正确性。

总之,贪心算法是一种简单而有效的问题求解方法,通过不断选择当前最优解,希望最终达到全局最优解。它在一些问题上具有高效性和简洁性,但并非适用于所有情况。

具体例子:

我们来举一个具体的例子来说明贪心算法的应用。

假设你是一个商人,要在一天内走访多个城市,每个城市都有一定数量的客户等待你的拜访。你想要制定一个行程计划,使得在有限的时间内拜访尽可能多的客户。

这个问题可以使用贪心算法来解决。一种贪心策略是每次选择距离当前位置最近的客户进行拜访。你可以从起始城市开始,选择最近的客户进行拜访,然后移动到下一个最近的客户,一直重复这个过程直到时间用尽。

这种贪心策略的原理是每次选择距离最近的客户,最大限度地减少行程中的路程,从而拜访更多的客户。虽然这个策略并不能保证一定能够找到最优解,但在很多情况下它能够得到接近最优解的结果,并且具有较高的效率。

需要注意的是,这个例子中贪心算法的应用是基于问题的特性,即选择最近的客户是每一步的局部最优解,并且每次选择不会影响到后续的决策。因此,贪心算法在这个问题上是有效的。

 2.什么是活动安排问题?

活动安排问题是贪心算法的经典应用之一。它的场景是给定一组活动,每个活动都有一个开始时间和结束时间,目标是安排出一个最大数量的相互兼容的活动集合,即这些活动之间不会相互冲突。

贪心算法在解决活动安排问题时的思路是选择结束时间最早的活动,这样可以腾出更多的时间去安排其他活动。具体步骤如下:

1. 将活动按照结束时间从早到晚进行排序。
2. 选择结束时间最早的活动作为第一个安排的活动。
3. 从剩余的活动中选择开始时间不早于已安排活动的结束时间的活动,并且结束时间最早。
4. 重复步骤3,直到没有可选择的活动为止。

贪心算法的关键在于证明这个贪心策略的正确性。对于活动安排问题,可以证明贪心选择最优解。假设存在一个最优解,其中包含了活动A和活动B,而我们的贪心策略没有选择其中一个。通过比较A和B的结束时间,我们可以发现选择结束时间较早的活动,能够为后续的活动安排腾出更多的空间。因此,我们的贪心策略可以得到最优解。

活动安排问题是贪心算法的经典案例,它的时间复杂度为O(nlogn),其中n是活动的数量。这个问题在诸如会议安排、课程表编排等实际场景中有着广泛的应用。

3.为什么要从结束时间开始排序

在活动安排问题中,选择按照结束时间来排序是因为这样的贪心策略能够最大程度地腾出时间空间,以容纳更多的活动。

考虑一下,如果我们选择按照开始时间来排序。在这种情况下,我们可能会选择一个很早开始但是持续时间很长的活动,这可能会占用较大的时间段,导致其他活动无法安排进来。

然而,如果我们选择按照结束时间来排序,我们能够优先选择结束时间早的活动,这样能够更快地释放出时间段,为后续的活动提供更多的可用时间。这种策略可以最大化地利用时间资源,以安排尽可能多的活动。

当然,按照结束时间排序并不是在所有情况下都适用的通用策略。有些特定情况下,可能会存在其他的排序策略。但在活动安排问题中,按照结束时间排序是常见且有效的贪心策略,它能够提供一个近似的最优解。

 4.GreedySelector算法

 完整功能代码:
 

template<class Type>
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;
		}
	}
}

这段代码实现了一个贪心选择算法来解决活动安排问题。让我逐行解释代码的功能:


template<class Type>
void GreedySelector(int n, Type s[], Type f[], bool A[])


这是一个模板函数的定义,它接受三个数组参数和一个布尔类型的输出数组。`n` 是活动的数量,`s[]` 是活动的开始时间数组,`f[]` 是活动的结束时间数组,`A[]` 是用来记录选择结果的布尔数组。

A[1] = true;
int j = 1;


将第一个活动设置为选中状态(`true`),并初始化变量 `j` 为 1,用于记录上一个选中的活动的索引。

for (int i = 2; i <= n; i++)
{
    if (s[i] >= f[j])
    {
        A[i] = true;
        j = i;
    }
    else
    {
        A[i] = false;
    }
}


从第二个活动开始遍历,判断当前活动的开始时间 `s[i]` 是否大于等于上一个选中的活动的结束时间 `f[j]`。如果满足这个条件,说明当前活动与前一个活动不冲突,可以选中该活动,并更新 `j` 为当前活动的索引。否则,当前活动与前一个活动冲突,不能选中该活动。

最终,布尔数组 `A[]` 记录了最优解中哪些活动被选中(`true`)或未被选中(`false`)。

这段代码的关键在于每次选择活动时,判断当前活动是否与前一个选中的活动冲突,只选取不冲突的活动。通过这种贪心选择策略,可以得到一个最大数量的相互兼容的活动集合。

 

 5.关于书上文字的解释:

这段文字是对贪心选择算法(Greedvselector)的解释。它使用集合 A 来存储所选择的活动,其中活动 i 在集合 A 中当且仅当 A[i] 的值为 true。变量 j 用于记录最近一次加入到 A 中的活动。由于输入的活动是按照它们的结束时间非递减序排列的,所以 f[j] 总是当前集合 A 中所有活动的最大结束时间,即 f[j] = max{f[i]}。

贪心算法 GreedySelector 从活动 1 开始选择,并将 j 初始化为 1,然后依次检查活动 i 是否与当前已选择的所有活动相容。如果相容,则将活动 i 加入到已选择活动的集合 A 中;否则不选择活动 i,而继续检查下一个活动与集合 A 中活动的相容性。由于 f[j] 总是当前集合 A 中所有活动的最大结束时间,所以活动 i 与当前集合 A 中所有活动相容的充分且必要条件是,其开始时间 s[i] 不早于最近加入集合 A 中的活动的结束时间 f[j]。如果活动 i 与之相容,则 i 成为最近加入集合 A 中的活动,并取代活动 j 的位置。由于输入的活动以其结束时间的非递减排列,因此算法 GreedySelector 每次总是选择具有最早结束时间的相容活动加入集合 A 中。按照这种方法选择相容活动可以尽可能地留下更多的时间段来安排未选择的活动,从而使剩余的可安排时间段最大化,以容纳尽可能多的相容活动。

贪心算法 GreedySelector 的效率非常高。当输入的活动已按照结束时间的非递减序排列时,算法只需 O(n) 的时间复杂度来安排活动,其中 n 是待安排的活动数量,使最多的活动能相容地使用公共资源。

6.代码实现:

C语言版:

#include <stdio.h>

void GreedySelector(int n, int s[], int f[], int A[]) {
    A[0] = 1;  // 第一个活动总是选中
    int j = 0; // 记录最近一次加入到 A 中的活动的索引

    for (int i = 1; i < n; i++) {
        if (s[i] >= f[j]) {
            A[i] = 1; // 选择活动 i
            j = i;
        } else {
            A[i] = 0; // 不选择活动 i
        }
    }
}

int main() {
    int n = 5; // 活动数量
    int s[] = {1, 3, 0, 5, 8}; // 活动的开始时间数组
    int f[] = {2, 4, 6, 7, 9}; // 活动的结束时间数组
    int A[n]; // 用于记录选择结果的数组

    GreedySelector(n, s, f, A);

    printf("选择的活动序号:");
    for (int i = 0; i < n; i++) {
        if (A[i] == 1) {
            printf("%d ", i + 1);
        }
    }
    printf("\n");

    return 0;
}

 代码解释:

在这个例子中,我们假设有 5 个活动,开始时间和结束时间分别用数组 s[]f[] 表示。A[] 是用于记录选择结果的数组,其中元素为 1 表示选择该活动,为 0 表示不选择该活动。

main() 函数中,我们调用 GreedySelector() 函数,传递活动数量 n、开始时间数组 s[]、结束时间数组 f[] 和结果数组 A[]。然后打印选择的活动序号,即结果数组中值为 1 的索引加 1。

这个例子中的输入数据和结果是固定的,您可以根据需要修改或扩展输入数据。请确保输入的活动已按照结束时间的非递减顺序排列,这样贪心算法才能正确工作。

C++:
 

#include <iostream>
#include <vector>

void GreedySelector(int n, std::vector<int>& s, std::vector<int>& f, std::vector<bool>& A) {
    A[0] = true; // 第一个活动总是选中
    int j = 0; // 记录最近一次加入到 A 中的活动的索引

    for (int i = 1; i < n; i++) {
        if (s[i] >= f[j]) {
            A[i] = true; // 选择活动 i
            j = i;
        } else {
            A[i] = false; // 不选择活动 i
        }
    }
}

int main() {
    int n = 5; // 活动数量
    std::vector<int> s = {1, 3, 0, 5, 8}; // 活动的开始时间数组
    std::vector<int> f = {2, 4, 6, 7, 9}; // 活动的结束时间数组
    std::vector<bool> A(n); // 用于记录选择结果的数组

    GreedySelector(n, s, f, A);

    std::cout << "选择的活动序号:";
    for (int i = 0; i < n; i++) {
        if (A[i]) {
            std::cout << i + 1 << " ";
        }
    }
    std::cout << std::endl;

    return 0;
}

这段代码与之前的 C 代码实现基本相同,只是使用了 C++ 的容器 std::vector 来代替数组,并使用了 std::coutstd::endl 来进行输出。

main() 函数中,我们定义了活动数量 n,开始时间数组 s,结束时间数组 f,以及用于记录选择结果的布尔型向量 A。然后调用 GreedySelector() 函数,传递这些参数,并在屏幕上打印选择的活动序号。

这个例子中的输入数据和结果是固定的,您可以根据需要修改或扩展输入数据。请确保输入的活动已按照结束时间的非递减顺序排列,这样贪心算法才能正确工作。

 

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

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

相关文章

网络安全面试题大全(整理版)500+面试题附答案详解,最全面详细,看完稳了

前言 随着国家政策的扶持&#xff0c;网络安全行业也越来越为大众所熟知&#xff0c;想要进入到网络安全行业的人也越来越多。 为了拿到心仪的Offer之外&#xff0c;除了学好网络安全知识以外&#xff0c;还要应对好企业的面试。 作为一个安全老鸟&#xff0c;工作这么多年&…

全网最全的网络安全技术栈内容梳理(持续更新中)

前言 本文篇幅比较长~~耐心看完哦~ 网络安全真的那么好吗 据我了解现在我国网络安全人才缺口相当大&#xff0c;预计在2023年这方面人才缺口达到327万&#xff0c;我每年这方面的大学生才2W多。现在各政企都在发展数字化变革&#xff0c;对网络安全方面人才也是垂涎若渴&…

【31】核心易中期刊推荐——电子信息技术计算机技术

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…

06SpringCloud rabbitmq安装

rabbitmq安装 说明&#xff1a;请使用资料里提供的CentOS-7-x86_64-DVD-1810.iso 安装虚拟机. 1. 安装依赖环境 在线安装依赖环境&#xff1a; yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c kernel-devel m4 ncurses-devel …

动态规划-概率DP

Bag of mice 题面翻译 https://www.luogu.com.cn/problem/CF148D 袋子里有 w w w 只白鼠和 b b b 只黑鼠 &#xff0c;A和B轮流从袋子里抓&#xff0c;谁先抓到白色谁就赢。A每次随机抓一只&#xff0c;B每次随机抓完一只之后会有另一只随机老鼠跑出来。如果两个人都没有抓到…

【小沐学GIS】基于Cesium实现三维数字地球Earth(CesiumJS入门安装)

文章目录 1、简介1.1 平台1.1.1 Cesium ion1.1.2 CesiumJS1.1.3 Cesium for Unity1.1.4 Cesium for Unreal1.1.4 Cesium for Omniverse1.1.5 Cesium for O3DE 1.2 支持的数据格式 2、CesiumJS安装3、代码测试3.1 安装node3.2 安装依赖项3.3 运行测试示例3.4 注册获取token 4、扩…

常见的前端框架

随着前端行业的发展&#xff0c;前端框架越来越多出现&#xff0c;为我们的项目开发工作带来了极大的便利&#xff0c;那目前主流的前端框架有哪些呢&#xff1f; 工作中我们常用的前端框架有vue框架、React框架、Bootstrap框架、Angular框架等&#xff0c;下面给大家简单介绍…

【AI绘图】二、stable diffusion环境准备与安装

前一篇&#xff1a;一、stable diffusion的发展史 放一张SD的效果图 硬件配置要求 Stable Diffusion是使用显卡生成图片&#xff0c;对电脑硬件有一定要求。 电脑配置最核心的关键点&#xff1a;看显卡、看内存、看硬盘、看 CPU。 显卡&#xff1a;N 卡&#xff08;英伟达 N…

基于内点法求解最优潮流研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Spring源码(二)— AbstractApplicationContext

上一篇文章简单的介绍了一下Spring框架大体的一个执行流程&#xff0c;整个专栏的内容也会根据第一篇序言中的流程图一步一步的向下梳理&#xff0c;并会慢慢补充更多的细节进去。 Test 创建ClassPathXmlApplicationContext来解析xml。 public class Test {public static vo…

剖析 OpenShift 中的 DNS

深入分析 OpenShift 内部 DNS OpenShift 中的DNS 相关组件及其配置1.1 Pod 中的 DNS 配置1.2 Pod 所在宿主机上的 DNS 配置及服务1.2.1 resolv.conf 文件 DNS 配置DNS 查询流程为什么需要内部 DNS&#xff1f; 本文基于 OpenShift 3.11&#xff0c;Kubernetes 1.11 进行测试 O…

2023/6/4周报

目录 摘要 论文阅读 1、标题和现存问题 2、使用GNN进行文本分类 3、INDUCT-GCN 4、实验准备 5、实验结果 深度学习 1、时空图的种类 2、图在环境中的应用 3、STGNN 总结 摘要 本周在论文阅读上&#xff0c;阅读了一篇InducT-GCN:归纳图卷积文本分类网络的论文。基…

python-pandas按各种时间统计和案例

使用到的库 pandas、matplotlib、numpy 使用到的函数 df.resample(“H”).sum() 参数 B business day frequency C custom business day frequency (experimental) D calendar day frequency W weekly frequency M month end frequency BM business month end frequency CBM…

【奶奶看了都会】云服务器ChatGLM模型fine-tuning微调,让你拥有自己的知识库

1.背景 大家好啊&#xff0c;上次给大家写了ChatGLM-6B的部署使用教程&#xff0c;【奶奶看了都会】云服务器部署开源ChatGLM-6B&#xff0c;让你拥有自己的ChatGPT 但是因为模型比较小的问题&#xff0c;所以日常工作中可能用不上。而且大家更希望的是模型能训练自己的数据&…

【Python Bokeh】零基础也能轻松掌握的学习路线与参考资料

Python Bokeh是一款为开发者提供数据可视化的Python库。它可以帮助开发者轻松地创建交互式网页应用程序&#xff0c;而无需编写大量的JavaScript代码。Bokeh支持各种绘图类型和工具&#xff0c;包括线图、散点图、条形图等。Python Bokeh非常适合在大数据分析、商业智能和数据科…

chatgpt赋能python:Python去除重复元素的几种方法

Python去除重复元素的几种方法 在Python编程中&#xff0c;去除列表、集合、字典等数据结构中的重复元素是一个常见的操作。本文将介绍Python中去除重复元素的几种方法&#xff0c;并分析它们的优缺点。 方法一&#xff1a;使用set去重 Set是Python中的一种集合类数据结构&a…

17_Linux根文件简介与Busybox构建文件系统

目录 根文件系统简介 文件目录简介 BusyBox简介 编译BusyBox构建根文件系统 修改Makefile添加编译器 busybox中文字符支持 配置 busybox 编译busybox 向根文件系统添加lib库 向rootfs的“usr/lib”目录添加库文件 创建其他文件夹 根文件系统初步测试 根文件系统简介…

Unity制作二次元卡通渲染角色材质——3、高光反射与ILM贴图

Unity制作二次元材质角色 回到目录 大家好&#xff0c;我是阿赵。 这里继续来讲二次元角色的材质。上次讲了光影的色阶化问题&#xff0c;这次继续讲光照模型效果的问题。 之前我们说过&#xff0c;光照模型的最后效果是&#xff1a; 环境色漫反射高光反射。 这里我们可以先忽略…

【嵌入式系统】思考题复习

嵌入式系统思考题 0. 名词解释1. 嵌入式系统概述2. ARM处理器体系结构3. ARM指令集4. S5PV210微处理器与接口5. ARM-Linux内核6. 嵌入式Linux文件系统7. 嵌入式Linux系统移植及调试8. 设备驱动程序设计9. QT图形界面应用程序开发基础10. SQLite数据库11. 嵌入式系统的开发设计案…

Qt6.5.1LTS搭建Android开发环境填坑

Qt6第二个LTS出来了&#xff0c;周日找时间安装并测试了Qt6.5LTS&#xff0c;安装我是按我之前的一个博客记录来做的&#xff0c;用的是国内境像&#xff0c;顺利快速安装完成&#xff0c;下面是设置的过程关键总结。 一、Devices Android设备(Device)选择 二、Kits &#xf…