活动选择问题 | 贪心算法 1

贪心法是一种算法范式,它逐个构建解决方案,始终选择下一个提供最明显和最直接好处的部分。贪心算法用于优化问题。 

如果问题具有以下属性,则可以使用 Greedy 解决优化问题: 

  • 在每一步中,我们都可以做出当前看起来最好的选择,从而得到完整问题的最优解。 

如果贪心算法可以解决问题,那么它通常会成为解决该问题的最佳方法,因为贪心算法通常比动态规划等其他技术更有效。但是贪心算法并不总是适用的。例如,Fractional Knapsack问题可以使用 Greedy 来解决,但是0-1 Knapsack 问题不能使用 Greedy 来解决。

以下是贪心算法的一些标准算法:

1)Kruskal 的最小生成树(MST): 

在 Kruskal 算法中,我们通过一条一条地挑选边来创建 MST。Greedy Choice 是在目前构建的 MST 中选取不会引起循环的最小权重边

2) Prim 的最小生成树 

同样在 Prim 的算法中,我们通过一条一条地挑选边缘来创建 MST。我们维护两个集合:一组已经包含在 MST 中的顶点和一组尚未包含的顶点。Greedy Choice 是选择连接两个集合的最小权重边

3) Dijkstra 的最短路径: 

Dijkstra 算法与 Prim 算法非常相似。最短路径树是逐边构建的。我们维护两个集合:一组已经包含在树中的顶点和一组尚未包含的顶点。贪婪选择是选择连接两个集合的边,并且在从源到包含尚未包含的顶点的集合的最小权重路径上

4)霍夫曼编码 

霍夫曼编码是一种无损压缩技术。它将可变长度的位代码分配给不同的字符。Greedy Choice 是将最少位长度的代码分配给出现频率最高的字符。

贪心算法有时也用于获得 Hard 优化问题的近似值。例如,旅行商问题是一个 NP-Hard 问题。这个问题的贪心选择是每一步都从当前城市中选择最近的未访问过的城市。这些解决方案并不总是产生最佳最优解,但可用于获得近似最优解。

在这里让我们看一个可以使用贪心算法解决的问题

问题:

你有n 个活动及其开始和结束时间。选择一个人可以执行的最大活动数,假设一个人一次只能从事一项活动。 

例子:  

输入: start[] = {10, 12, 20}, finish[] = {20, 25, 30}
输出: 0 2
解释:一个人最多可以进行两项活动。
可以执行的最大活动集 是 
{0, 2} [这些是 start[] 和 finish[] 中的索引]

输入:开始[] = {1, 3, 0, 5, 8, 5},完成[] = {2, 4, 6, 7, 9, 9};
输出: 0 1 3 4
解释:一个人最多可以进行四项活动。
可以执行的最大活动集 是 
{0, 1, 3, 4} [这些是 start[] 和 finish[] 中的索引

推荐做法
活动选择
Prim 的最小生成树

方法要解决问题,请遵循以下想法:

贪心选择总是选择剩余活动中完成时间最短且开始时间大于或等于先前选择的活动的结束时间的下一个活动。我们可以根据活动的完成时间对活动进行排序,以便我们始终将下一个活动视为完成时间最短的活动

按照给定的步骤解决问题:

  • 根据完成时间对活动进行排序 
  • 从排序的数组中选择第一个活动并打印它 
  • 对排序数组中的剩余活动执行以下操作
    • 如果此活动的开始时间大于或等于先前选择的活动的结束时间,则选择此活动并打印它

注意:在实现中,假设活动已经按照完成时间排序

下面是上述方法的实现。

// C++ program for activity selection problem.
 
// The following implementation assumes that the activities
// are already sorted according to their finish time
#include <bits/stdc++.h>
using namespace std;
 
// Prints a maximum set of activities that can be done by a
// single person, one at a time.
void printMaxActivities(int s[], int f[], int n)
{
    int i, j;
 
    cout << "Following activities are selected" << endl;
 
    // The first activity always gets selected
    i = 0;
    cout << i << " ";
 
    // Consider rest of the activities
    for (j = 1; j < n; j++) {
        // If this activity has start time greater than or
        // equal to the finish time of previously selected
        // activity, then select it
        if (s[j] >= f[i]) {
            cout << j << " ";
            i = j;
        }
    }
}
 
// Driver code
int main()
{
    int s[] = { 1, 3, 0, 5, 8, 5 };
    int f[] = { 2, 4, 6, 7, 9, 9 };
    int n = sizeof(s) / sizeof(s[0]);
 
    // Function call
    printMaxActivities(s, f, n);
    return 0;
}
// this code contributed by shivanisinghss2110
输出
Following activities are selected
0 1 3 4 

时间复杂度: O(N)
辅助空间: O(1)

贪婪选择如何适用于根据完成时间排序的活动? 

设给定的活动集为 S = {1, 2, 3, …n},活动按完成时间排序。贪婪的选择是总是选择活动 1。为什么活动 1 总是提供最优解之一?

 我们可以证明,如果存在第一个活动不是 1 的另一个解决方案 B,那么也存在与第一个活动相同大小的活动 1 的解决方案 A。设 B 选择的第一个活动为 k,则总存在 A = {B – {k}} U {1}。

注: B 中的活动是独立的,k 的完成时间是所有活动中最小的。因为 k 不为 1,所以 finish(k) >= finish(1))

当给定的活动未排序时如何实施? 

我们为活动创建一个结构/类。我们按完成时间对所有活动进行排序。一旦我们对活动进行排序,我们就应用相同的算法。

下图是上述方法的说明: 

下面是上述方法的实现:

// C++ program for activity selection problem
// when input activities may not be sorted.
#include <bits/stdc++.h>
using namespace std;
 
// A job has a start time, finish time and profit.
struct Activitiy {
    int start, finish;
};
 
// A utility function that is used for sorting
// activities according to finish time
bool activityCompare(Activitiy s1, Activitiy s2)
{
    return (s1.finish < s2.finish);
}
 
// Returns count of the maximum set of activities that can
// be done by a single person, one at a time.
void printMaxActivities(Activitiy arr[], int n)
{
    // Sort jobs according to finish time
    sort(arr, arr + n, activityCompare);
 
    cout << "Following activities are selected :\n";
 
    // The first activity always gets selected
    int i = 0;
    cout << "(" << arr[i].start << ", " << arr[i].finish
         << ")";
 
    // Consider rest of the activities
    for (int j = 1; j < n; j++) {
        // If this activity has start time greater than or
        // equal to the finish time of previously selected
        // activity, then select it
        if (arr[j].start >= arr[i].finish) {
            cout << ", (" << arr[j].start << ", "
                 << arr[j].finish << ")";
            i = j;
        }
    }
}
 
// Driver code
int main()
{
    Activitiy arr[] = { { 5, 9 }, { 1, 2 }, { 3, 4 },
                        { 0, 6 }, { 5, 7 }, { 8, 9 } };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Function call
    printMaxActivities(arr, n);
    return 0;
}
输出
Following activities are selected :
(1, 2), (3, 4), (5, 7), (8, 9)

时间复杂度: O(N log N),如果输入活动可能无法排序。如果输入活动总是排序,则需要 O(n) 时间。
辅助空间: O(1)

使用优先级队列的活动选择问题:

我们可以使用 Min-Heap 来获得完成时间最短的活动。Min-Heap可以使用优先级队列来实现

按照给定的步骤解决问题:

  • 创建一个优先级队列(Min-Heap)并将活动推送到其中。
  • 将优先级队列的顶部推入答案向量并将变量start设置为第一个活动的开始时间,将end设置为活动的结束时间
  • 当 priority 不为空时,请执行以下操作:
    • 取优先级队列的顶部并检查
    • 如果此活动的开始时间大于或等于最后选择的活动的结束时间,则将此活动推入答案向量
    • 否则忽略它
  • 打印选择的活动,存储在答案向量中

下面是上述方法的实现:

// C++ program for activity selection problem
// when input activities may not be sorted.
#include <bits/stdc++.h>
using namespace std;
 
void SelectActivities(vector<int> s, vector<int> f)
{
    // Vector to store results.
    vector<pair<int, int> > ans;
 
    // Minimum Priority Queue to sort activities in
    // ascending order of finishing time (f[i]).
 
    priority_queue<pair<int, int>, vector<pair<int, int> >,
                   greater<pair<int, int> > >
        p;
 
    for (int i = 0; i < s.size(); i++) {
        // Pushing elements in priority queue where the key
        // is f[i]
        p.push(make_pair(f[i], s[i]));
    }
 
    auto it = p.top();
    int start = it.second;
    int end = it.first;
    p.pop();
    ans.push_back(make_pair(start, end));
 
    while (!p.empty()) {
        auto itr = p.top();
        p.pop();
        if (itr.second >= end) {
            start = itr.second;
            end = itr.first;
            ans.push_back(make_pair(start, end));
        }
    }
    cout << "Following Activities should be selected. "
         << endl
         << endl;
 
    for (auto itr = ans.begin(); itr != ans.end(); itr++) {
        cout << "Activity started at " << (*itr).first
             << " and ends at " << (*itr).second << endl;
    }
}
 
// Driver code
int main()
{
    vector<int> s = { 1, 3, 0, 5, 8, 5 };
    vector<int> f = { 2, 4, 6, 7, 9, 9 };
 
    // Function call
    SelectActivities(s, f);
 
    return 0;
}
输出
Following Activities should be selected​​​​​​​Activity started at ​​​​​​​:1 and ends at​​​​​​​ 2
Activity started at ​​​​​​​:3 and ends at​​​​​​​ 4 
Activity started at ​​​​​​​:5 and ends at​​​​​​​ 7 
Activity started at ​​​​​​​:8 and ends at 9 

时间复杂度: O(N * log N)
辅助空间: O(N)

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

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

相关文章

MongoDB 6.0 (四)聚合操作

一、 聚合框架的作用 1. 什么是MongoDB 聚合框架 MongoDB 聚合框架(Aggregation Framework)是一个计算框架,它可以: • 作用在一个或几个集合上; • 对集合中的数据进行的一系列运算; • 将这些数据转化为期望的形式; 从效果而言,聚合框架相当于SQL 查询中的: …

【Mysql系列】——详细剖析数据库“索引”【上篇】

【Mysql系列】——详细剖析数据库中的核心知识【索引】&#x1f60e;前言&#x1f64c;索引索引概述为什么需要索引&#xff1f;索引的优缺点索引结构索引的结构为什么不是二叉树和红黑树&#xff1f;索引的B树结构索引的Hash结构Hash结构索引的特点思考&#xff1a;为什么Inno…

MySQL中多表查询(多表关系:一对多、多对多、一对一,分类:连接查询:内连接、外连接、自连接、联合查询,子查询:标量子查询、列子查询、行子查询、表子查询)

多表关系&#xff1a; 一对多&#xff1a; 多对多&#xff1a; 一对一&#xff1a; 我们发现我们利用DQL中的select语句查询多张表的时候&#xff0c;会出现一个数学现象&#xff0c;叫做笛卡尔积 因此我们可以加上where语句来限定条件&#xff1a; 内连接&#xff1a; 此处in…

计算机网络面试八股文攻略(一) —— OSI 七层模型

一、简述 本系列将对面试中与计算机网络相关的知识进行讲解与分析。 本篇为 OSI 七层网络模型的相关知识。 二、概念 OSI 七层网络模型是国际标准化组织&#xff08;ISO&#xff09;制定的一个用于计算机或通信系统间互联的标准体系。它是一个七层的、抽象的模型体&#xff…

A Causal Debiasing Framework for Unsupervised Salient Object Detection

背景知识 显著性检测 简单就是使用图像处理技术和计算机视觉算法来定位图片中最“显著”的区域。显著区域就是指图片中引人注目的区域或比较重要的区域&#xff0c;例如人眼在观看一幅图片时会首先关注的区域。 chatGPT4的回答 计算机视觉中的显著性检测&#xff08;Visual…

从事6个月软件测试,目前只会功能测试迷茫了...

前言 (来自一位粉丝的投稿)来这个公司大半年&#xff0c;现在主要做的是类似于淘宝的购物商城&#xff0c;以前也做应用系统什么的&#xff0c;可是感觉公司的软件测试岗位都是不着边的&#xff0c;因为做的都是功能测试&#xff0c;来了这么久&#xff0c;没接触过技术性的东…

美丽苏大,清华博士,年轻硕导,招收研究生了!

Datawhale学术 导师&#xff1a;张正超&#xff0c;苏州大学&#xff0c;Datawhale成员导师信息本人于2022年取得清华大学博士学位&#xff0c;目前是苏州大学计算机科学与技术学院的硕士生导师&#xff0c;2023年可招收计算机科学与技术、软件工程、人工智能及大数据技术与工程…

微服务保护Sentinel一站式学习

微服务保护Sentinel 雪崩问题 解决雪崩问题的四种常见方式&#xff1a; 超时处理&#xff1a;设定超时时间&#xff0c;请求超过一定时间没有响应就返回错误信息&#xff0c;不会无休止等待。如果设置一秒钟没响应返回&#xff0c;即1s释放连接&#xff0c;这1s中有好多个请求…

BOSS直拒、失联招聘,消失的“金三银四”,失业的测试人出路在哪里?

裁员潮涌&#xff0c;经济严冬。最近很多测试人过得并不好&#xff0c;行业缩水对测试岗位影响很直接干脆&#xff0c;究其原因还是测试门槛在IT行业较低&#xff0c;同质化测试人员比较多。但实际上成为一位好测试却有着较高的门槛&#xff0c;一名优秀的测试应当对产品的深层…

Stable Diffusion 视频和图片帧互换以及AI动画帧生成

Stable Diffusion 只做AI动画是基于把原有视频按照帧进行提取之后对每一帧的图像进行标准化流程操作&#xff0c;中间可以掺杂Controlnet对人物进行控制&#xff0c;使用关键词对画面进行控制&#xff0c;但是很多小伙伴不太会掌握一些编辑视频软件或者python的操作导致视频转帧…

Java 深入理解Servlet

动态资源与静态资源区别 servlet三及相关接口简介servet 执行过程servlet路径映射servlet生命周期(重点) --理解&#xff08;重点&#xff09;Servlet自动加载Servlet线程安全Servlet相关接口详解ServletContext对象 --知识点 一、Web项目结构 |- WebRoot : web应用的根目录…

【linux】常用命令大全(入门必备)

这篇文章涵盖了linux中常用的所有指令&#xff0c;欢迎大家阅读查询。(如有不正确的地方&#xff0c;各位大佬可以在评论区指出&#xff0c;我会及时进行更正)。 文章目录登录远程服务器ssh添加删除用户当前路径pwd列出文件目录ls进入cdtreewhoami创建文件touch创建目录mkdir删…

【C语言学习】循环结构和选择结构

C语言中有三大结构&#xff0c;分别是顺序结构、选择结构和循环结构&#xff08;分支结构&#xff09;&#xff1a; C语言顺序结构就是让程序按照从头到尾的顺序依次执行每一条C语言代码&#xff0c;不重复执行任何代码&#xff0c;也不跳过任何代码。 C语言选择结构也称分支结…

都说IT行业饱和了,2023年成为程序员还有发展前景吗?

程序员饱和了吗&#xff1f;初级码农肯定是算饱和了&#xff0c;因为大部分的互联网企业开始提高招聘要求了&#xff0c;比如技能要求、两三年工作经验、项目经验、软实力等&#xff0c;是按照中级开发人员的标准来的。所以干程序员还是有发展前景的&#xff0c;你的技能达标了…

Linux常用命令——locate命令

在线Linux命令查询工具 locate 比 find 好用的文件查找工具 补充说明 locate 让使用者可以很快速的搜寻档案系统内是否有指定的档案。其方法是先建立一个包括系统内所有档案名称及路径的数据库&#xff0c;之后当寻找时就只需查询这个数据库&#xff0c;而不必实际深入档案…

虹科喜报 | 虹科技术工程师【国内首批】拿下Redis认证开发者证书!

要说虹科数据库技术工程师有多强悍&#xff0c;认证考试2022年12月上线&#xff0c;次年2月就以全国首批速度强势通过考试&#xff0c;并于两周后正式收到【Redis认证开发人员】证书&#xff01; 虹科小云忍不住浅浅炫耀一下&#xff1a; 或许大家对Redis企业版数据库认证开发…

前端面试题之html css篇

文章目录1.什么是盒模型2.行内元素有哪些&#xff1f;块级元素有哪些&#xff1f; 空(void)元素有那些&#xff1f;行内元素和块级元素有什么区别&#xff1f;3.简述src和href的区别4.什么是css Hack5.什么叫优雅降级和渐进增强6.px和em的区别7.HTML5 为什么只写< !DOCTYPE …

[linux虚拟机]网络连接的三种模式和重要文件夹

桥接模式: 虚拟系统可以和外部系统通讯,但容易造成IP冲突NAT模式,网络地址转换模式,虚拟系统可以和外部系统通讯,不造成IP冲突主机模式:独立的系统 /bin [常用] (/usr/bin 、 /usr/local/bin) 是 Binary 的缩写, 这个目录存放着最经常使用的命令/sbin (/usr/sbin 、 /usr/loca…

2023年非业绩亏损ST股票投资策略研究报告

第一章 ST 股票概况 ST 股票是指中国股市上的一种特殊类型的股票&#xff0c;全称为“特别处理股票”&#xff0c;简称为 ST 股票。1998年4月22日&#xff0c;沪深证券交易所宣布将对财务状况和其他财务状况异常的上市公司的股票交易进行特别处理&#xff0c;由于“特别处理”…

VirtualBox安装centos宿主机与虚拟机网络互通、多个虚拟机之间网络互通、虚拟机可上外网

一&#xff0c;虚拟机的网络配置连接方式 选择 桥接网卡&#xff0c;界面名称 选择 当前宿主机能上网的网卡我现在电脑当前能上网的 网络名称是Remote NDIS .... &#xff0c;所以上面的界面名称选它&#xff1a;修改之后&#xff0c;重启centos虚拟机二&#xff0c;配置虚拟机…