【数据结构】贪心算法

一.贪心算法的定义

        贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解

        贪心算法的结果是最优解的最好近似。

优点:简单,高效。

缺点:可能不是正确的或最优的解

二.引例

当一个问题具有最优子结构性质时,可以用动态规划求解。也可以用贪心算法来求解。

哈夫曼编码:每次选择集合中权值最小的两个子树构成一棵树。

思想:贪心选择思想。

三.贪心算法的基本步骤与实现

1.建立数学模型来描述问题;

2.把求解的问题分成若干个子问题;

3.对每一个子问题求解,得到子问题的局部最优解;

4.把子问题的局部最优解合成原来问题的解。

四.贪心算法的应用

1.活动安排问题

(1)问题描述

1)有n个活动;

2)活动j在$s_j$时刻开始,$f_j$时刻结束;

3)如果两个活动不重叠,则这两个活动是可以兼容的;

4)目标:找到相互兼容的最大活动子集

(2)活动相容性:

设有n个活动的集合E={1,2,……,n},其中,每个活动都要求使用同一资源,如会场等。

而在同一时间内,只有一个活动能够使用该资源。

每个活动i都有一个要求使用该资源的起始时间$s_i$和一个结束时间$f_i$,且$s_i$<$f_i$

如果选择了活动i,则它在半开时间区间[$s_i$,$f_i$)内占用资源。

若区间[$s_i$,$f_i$)与区间[$s_j$,$f_j$)不相交,则称活动i与活动j相容。

(3)贪心策略:

先安排结束时间最早的活动,可以使得剩余的时间极大化,从而安排更多的活动。

(4)伪代码:

1.将所有活动按照结束时间从小到大排列;

2.扫描所有活动的开始时间与结束时间,若扫描到活动i的开始时间早于最近安排的活动j的结束时间,则不安排活动i,否则,安排活动i。

(5)代码:

int greedySelector(int s[],int f[],bool a[],int n){
    //n代表事件个数,bool类型的数组a表示活动i是否被安排
    //各活动的起始时间和结束时间存储于数组s和f中且按结束时间的非减序排序
    int i=0,j=0,count=0;//i表示处理的第i个活动,j表示刚刚安排的活动,count记录安排活动的数量
    //初始化
    a[i]=true;//安排第一个事件
    j=0;
    count++;
    for(i=1;i<n;i++){
        if(s[i]>f[j]) {
            a[i]=true;
            j = i;
            count++;
        }
        else{
            a[i]=false;
        }
    }
    return count;
}

 

(6)其他贪心策略:

1)最早开始时间

按照开始时间$s_i$非递减排序

2)最早结束时间 

按照结束时间$s_i$非递减排序

3)最短间隔

按照间隔长度$f_i-s_i$非递减排序

4)最小冲突

对于每个活动,计算该活动的冲突活动数$c_j$,并按照$c_j$非递减排序

(7)证明贪心算法对于活动安排问题的求解是整体最优解:

对于活动安排问题来说:

最优解即为:使得相容集合的规模最大

数学归纳法进行证明)

证明:

设E={1,2,……,n}活动集合(集合有序)

且按照活动安排结束时间递增排序,即:活动1具有最早的完成时间

假设:活动安排中有一个包含贪心选择的最优解

设A$\subseteq$E是该问题的一个最优解,且集合A也有序,对于A中的活动,将其表示为{$k_1,k_2,...,k_j$},则有活动的开始时间集合S={$s[k_1],s[k_2],...s[k_j]$},以及结束时间集合F=$\{f[k_1],f[k-2],...,f[k_j]\}$

找到一个集合A,首先:A是问题最优解;其次,A是贪心选择出来的集合。

当k=1时,A即为所求。

当k!=1时,设$B=$$A-\{k_1\}\cup\{1\}=\{1,k_2,k_3,...,k_j\}$

由于,$f[1]\leqslant f[k]$,将集合A更改之后,整个集合仍然相容,元素个数也没有改变,集合B也是最优解。

同理,以及将A中的元素替换,由于贪心选择的原理,每次选择结束时间最早的事件,则替换之后,集合仍然是相容的,将所有元素均替换为贪心选择的元素,则集合既是贪心选择的结果,也是最优解,即:贪心选择出的集合是最优解,得证。#

五.贪心算法的基本要素

1.贪心选择性质

所求问题的整体最优解可以通过一系列局部最优的选择达到。

用数学归纳法证明,通过每步的贪心选择,最终可以得到问题的整体最优解。

2.最优子结构性质

当一个问题的最优解包含其子问题的最优解,称此问题具有最优子结构性质。

问题的最优子结构性质是该问题可以用动态规划算法或者贪心算法求解的关键特征。

3.贪心算法和动态规划差别

动态规划:自底向上

贪心算法:从开始逐次迭代

0-1背包问题:

问题描述:

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

背包问题:

问题描述:

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

这两类问题都具有最优子结构性质,但是背包问题可以用贪心算法求解,而0-1背包问题却不能用贪心算法求解。

用贪心算法求解背包问题的基本步骤:

1.计算每种物品单位重量的价值$\frac{v_i}{w_i}$;

2.依据贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包; 

3.若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包;

4.依照此策略一直进行下去,直到背包装满为止。

代码实现:

#include <iostream>
using namespace std;

struct node{
    float weight;
    float value;
    int number;
};

int greedySelector(int s[],int f[],bool a[],int n);
float knapsack(float c,int n,float v[],float w[],float x[]);
int partition(struct node a[],int first,int end);
void quickSort(struct node a[],int first,int end);


int main() {
    int n=5;
    float v[]={10,40,20,30,25};
    float w[]={15,12,8,9,10};
    float x[5];
    float c=21.5;
    knapsack(c,n,v,w,x);
    for(int i=0;i<n;i++){
        cout<<x[i]<<" ";
    }
    cout<<endl;
    return 0;
}

int greedySelector(int s[],int f[],bool a[],int n){
    //n代表事件个数,bool类型的数组a表示活动i是否被安排
    //各活动的起始时间和结束时间存储于数组s和f中且按结束时间的非减序排序
    int i=0,j=0,count=0;//i表示处理的第i个活动,j表示刚刚安排的活动,count记录安排活动的数量
    //初始化
    a[i]=true;//安排第一个事件
    j=0;
    count++;
    for(i=1;i<n;i++){
        if(s[i]>f[j]) {
            a[i]=true;
            j = i;
            count++;
        }
        else{
            a[i]=false;
        }
    }
    return count;
}

float knapsack(float c,int n,float v[],float w[],float x[]){
    //函数的返回值表示总价值
    //c表示背包容量
    //n表示物品个数
    //数组v表示价值value,数组w表示重量weight,数组x表示每个物品放入背包的比例
    struct node *p=new struct node[n];
    int i,j;
    float sum=0;
    for(i=0;i<n;i++){
        p[i].number=i;
        p[i].value=v[i];
        p[i].weight=w[i];
        x[i]=0;
    }
    quickSort(p,0,n-1);

    for(i=0;i<n;i++){
        if(p[i].weight>c){
            break;
        }
        else{
            x[p[i].number]=1;
            sum+=p[i].value;
            c-=p[i].weight;
        }
    }
    if(i<n){
        x[p[i].number]=c/p[i].weight;
        sum+=p[i].value*c/p[i].weight;
    }
    delete []p;
    return sum;
}

int partition(struct node a[],int first,int end){
    int i=first,j=end;
    struct node temp;
    while(i<j){
        while(i<j&&(a[j].value/a[j].weight)<=(a[i].value/a[i].weight)){
            --j;
        }
        if(i<j){
            temp=a[i];
            a[i]=a[j];
            a[j]=temp;
        }
        while(i<j&&(a[j].value/a[j].weight)<=(a[i].value/a[i].weight)){
            ++i;
        }
        if(i<j){
            temp=a[i];
            a[i]=a[j];
            a[j]=temp;
        }
    }
    return i;//i==j时,返回轴值
}

void quickSort(struct node a[],int first,int end){
    if(first<end){
        int pos=partition(a,first,end);
        quickSort(a, first, pos-1);
        quickSort(a, pos+1, end);
    }
}

贪心算法不适用于0-1背包问题:

对于0-1背包问题,贪心算法得不到最优解。

无法保证最终能够将背包装满,部分闲置的背包空间使得单位重量的价值变低了。

在考虑0-1背包问题时,应比较选择该物品和不选择该物品所导致的最终方案,然后再做出最好选择。由此导出了许多相互重叠的子问题,这正是利用动态规划求解的重要特征。

 

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

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

相关文章

《Mamba: Linear-Time Sequence Modeling with Selective State Spaces》阅读笔记

论文标题 《Mamba: Linear-Time Sequence Modeling with Selective State Spaces》 利用选择性状态空间的线性时间序列建模 作者 Albert Gu 和 Tri Dao Albert Gu 来自卡内基梅隆大学机器学习系&#xff0c;Mamba 脱胎于 Albert Gu 的前作 S4 架构。 Tri Dao 来自普林斯顿…

赛氪为第五届全球校园人工智能算法精英大赛决赛提供技术支持

12月10日&#xff0c;以“智青春算未来”为主题的2023年第五届全球校园人工智能算法精英大赛全国总决赛在河海大学江宁校区举行。本次大赛由江苏省人工智能学会主办&#xff0c;自9月份启动以来&#xff0c;共吸引了全国近400所高校的3000多支参赛团队参加。经过校赛、省赛选拔…

C语言:高精度除法(除低精度)

P1480 A/B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 由图知&#xff0c;被除数的上一位的余数乘10加这位就是这一位结果的除数。 c[i] (d * 10 a[i]) / b #include<stdio.h> #include<string.h> char x[50005];//存储被除数&#xff0c;转为字符…

二百一十七、Flume——Flume拓扑结构之聚合的开发案例(亲测,附截图)

一、目的 对于Flume的聚合拓扑结构&#xff0c;进行一个开发测试 二、聚合 &#xff08;一&#xff09;结构含义 这种模式是我们最常见的&#xff0c;也非常实用。日常web应用通常分布在上百个服务器&#xff0c;大者甚至上千个、上万个服务器产生的日志&#xff0c;处理起来…

Java基础:如何创建多层文件夹

一、单层多个 代码实现如下&#xff1a; public class Main {public static void main(String[] args) {//在D盘中创建File file new File("D:"File.separator"docum");file.mkdir();//在D盘中的docum目录中创建file new File("D:\\docum" Fi…

[pasecactf_2019]flask_ssti proc ssti config

其实这个很简单 Linux的/proc/self/学习-CSDN博客 首先ssti 直接fenjing一把锁了 这里被加密后 存储在 config中了 然后我们去config中查看即可 {{config}} 可以获取到flag的值 -M7\x10wd94\x02!-\x0eL\x0c;\x07(DKO\r\x17!2R4\x02\rO\x0bsT#-\x1cZ\x1dG然后就可以写代码解…

Vue表格自定义合计、小计功能

一、合计 <template> <avue-crud:option"optiondata":table-loading"loading":data"testdata":page.sync"page":span-method"spanMethod"ref"cruddata"current-change"currentChangedata"si…

Unity | Shader基础知识(第四集:Shader结构体)

一、本节介绍 上一集&#xff0c;我们做了一个案例&#xff0c;这一集&#xff0c;我们继续讲一个语法&#xff0c;在shader里写结构体。 二、结构体的需求 1.shader里是不好随便去声明数据的&#xff0c;我们前面传入数据时&#xff0c;用的是括号传入&#xff08;如图&…

Redis怎么测?这篇文章写的太全了

Redis是一个高性能、内存数据库和缓存系统&#xff0c;在开发和生产环境中被广泛应用。本文将介绍如何进行有效的Redis软件测试&#xff0c;以确保其稳定性、高性能和可靠性。 Redis作为一种非关系型数据库和缓存系统&#xff0c;被广泛用于支持高流量、低延迟的应用。为了保证…

iic应用篇

一.iic的优点 1. IIC总线物理链路简单&#xff0c;硬件实现方便&#xff0c;扩展性非常好&#xff08;1个主机控制器可以根据需求增加从机数量&#xff0c;同时删减从机数量也不会影响总线通信&#xff09;&#xff1b;IIC总线只需要SDA和SCL两条信号线&#xff0c;相比于PCI/…

锂电池基础知识及管理方式总结

这两天在排查一个锂电池无法充电的问题&#xff0c;用的是电池管理芯片BQ25713&#xff0c;网上相关的资料也很少&#xff0c;查看数据手册时&#xff0c;里面也有很多术语参数等不是很理解&#xff0c;所以&#xff0c;在此对锂电池的基础知识做个简单的总结&#xff0c;方面后…

详解Django+Vue+Docker搭建接口测试平台实战

一. 开头说两句 正好接口自动化测试平台需要迁移到新的测试服务器上&#xff0c;就想要体验一番Docker的“一次构建&#xff0c;处处运行”。这篇文章简单介绍了下这次部署的过程&#xff0c;其中使用了Dockerfile定制镜像和Docker-Compose多容器编排。 二. 项目介绍 项目采…

Python-乒乓球小游戏【附完整源码】

乒乓球小游戏 乒乓球小游戏是一个简单而有趣的2D页面交互式游戏&#xff0c;玩家可以通过键盘输入来控制球拍上下移动来接球&#xff0c;从而体验乒乓球的乐趣。该游戏有单人和双人两种模式 运行效果&#xff1a; 一&#xff1a;主程序&#xff1a; import sys import cfg …

app自动化测试(Android)

Capability 是一组键值对的集合&#xff08;比如&#xff1a;"platformName": "Android"&#xff09;。Capability 主要用于通知 Appium 服务端建立 Session 需要的信息。客户端使用特定语言生成 Capabilities&#xff0c;最终会以 JSON 对象的形式发送给 …

芝麻杂草目标检测数据集VOC+YOLO格式近1300张

芝麻&#xff0c;芝麻科芝麻属的一年生草本植物&#xff0c;茎中空或具白色髓部&#xff1b;叶子为卵形&#xff1b;花朵单生或少数同生于腋下&#xff0c;呈白色&#xff1b;芝麻蒴果基部钝圆&#xff0c;顶部有尖&#xff0c;中间有棱&#xff1b;芝麻的种子通常呈扁平椭圆形…

k8s-service 7

由控制器来完成集群的工作负载&#xff0c;service&#xff08;微服务&#xff09;是将工作负载的应用暴露出去&#xff0c;从而解决访问问题 作用&#xff1a;无论是在集群内还是集群外&#xff0c;都可以访问pod上的应用&#xff0c;其实现对集群内的应用pod自动发现和负载均…

Linux面试题分享:从入门到精通的全面指南

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Llama2-Chinese-7b-Chat安装部署

文章目录 前言一、文件介绍 &#x1f4c1;二、环境配置 ♟三、Llama2-Chinese-7b-Chat下载 ⏬总结 前言 本文主要介绍如何使用Llama2-Chinese-7b-Chat&#xff0c;最后的效果如图所示&#xff1a; 一、文件介绍 &#x1f4c1; ⬇️ 下载地址&#xff1a;https://pan.baidu.…

软件测试工程师要掌握哪些专业技能

1.软件测试理论知识&#xff1a;掌握软件测试的基本概念、测试方法、测试技术和测试流程&#xff0c;包括黑盒测试、白盒测试、性能测试、安全测试等。 2.编程语言和脚本语言&#xff1a;掌握至少一种编程语言和脚本语言&#xff0c;例如Java、Python、JavaScript等。 3.自动化…

微服务网关Gateway

springcloud官方提供的网关组件spring-cloud-starter-gateway,看pom.xml文件,引入了webflux做响应式编程,请求转发用到了netty的reactor模型。hystrix停止维护后,官方推荐resilience4j做服务熔断,网关这里也能看到依赖。 对于网关提供的功能,大方向上主要是服务路由转发…