当前位置: 首页 > news >正文

详解贪心算法

贪心算法(Greedy Algorithm) 概述:

贪心算法是一种在求解最优化问题时采取的一种常用算法策略。贪心算法的基本思想是,每次选择当前情况下的局部最优解,并相信这个局部最优解能够导致全局最优解。贪心算法通过迭代的方式一步步地构建最优解,并不进行回溯。

贪心算法的一般步骤:

1. 将问题分解成多个子问题;
2. 对每个子问题,确定一个最优解;
3. 对每个子问题的最优解进行合并,得到原问题的最优解。


贪心算法的正确性需要满足两个条件:

1.最优子结构:问题的最优解能够由子问题的最优解组合而成。
2. 贪心选择性:通过局部最优选择能够得到全局最优解。


贪心算法适用的问题一般具有以下特点:

1. 子问题的最优解能够推导出原问题的最优解;
2. 子问题的最优解构成原问题的最优解时,原问题的最优解也能由它推导出。

贪心算法的优点是简单、高效,时间复杂度通常较低。然而,贪心算法并不适用于所有问题,有些问题需要使用其他更复杂的算法来求解。在使用贪心算法时,需要仔细分析问题的特点并证明贪心策略的正确性。


由于贪心是一种思想,没有具体的算法模板,而且贪心一般不会单独作为一种算法出现在题目中,一般会跟其他算法结合在一起出现。例如:动态规划、递归、高级数据结构等。在此基础上保证每一步时最优解的情况下就可以得到最优的答案。下面我们将以例题的形式让大家来了解这种思想。


例题一: 

AcWing 3769. 移动石子

题目:

一共有 n 个箱子排成一排,从左到右依次编号为 1∼n。

其中,第 i 号箱子中放有 ai个石子。

现在,你可以进行最多 d 次操作。

每次操作可以将一个石子从一个箱子移动至另一个与其相邻的箱子里。

我们希望通过合理操作使得 1 号箱子内的石子数量尽可能大。

请问,这个最大可能值是多少?

输入格式

第一行包含整数 T,表示共有 T 组测试数据。

每组数据第一行包含两个整数 n和 d。

第二行包含 n 个整数 a1,a2,…,an。

输出格式

每组数据输出一行结果,表示答案。

数据范围

1≤T≤100,
1≤n,d≤100,
0≤ai≤100.

输入样例:
3
4 5
1 0 3 2
2 2
100 1
1 8
0
输出样例:
3
101
0

解题思路:

这个题很明显贪心思想,要让第一个箱子尽可能多的石子,在操作次数的限制下,我们最优解,要从第二个箱子开始贪心,第二个、第三个...,这样可以使操作次数尽可能的少。

 


AC代码:
#include<iostream>
using namespace std;
const int N=105;
int t,n,d;
int a[N];
int main(){cin>>t;while(t--){cin>>n>>d;for(int i=1;i<=n;i++)cin>>a[i];int k=2;while(d){if(k>n)break;if(d>=a[k]*(k-1)){a[1]+=a[k];d-=a[k]*(k-1);}else{a[1]+=d/(k-1);d=0;}k++;}cout<<a[1]<<endl;}return 0;
}

例题二:

洛谷 P1007 独木桥

题目背景

战争已经进入到紧要时间。你是运输小队长,正在率领运输部队向前线运送物资。运输任务像做题一样的无聊。你希望找些刺激,于是命令你的士兵们到前方的一座独木桥上欣赏风景,而你留在桥下欣赏士兵们。士兵们十分愤怒,因为这座独木桥十分狭窄,只能容纳 1 个人通过。假如有 2 个人相向而行在桥上相遇,那么他们 2 个人将无法绕过对方,只能有 1 个人回头下桥,让另一个人先通过。但是,可以有多个人同时呆在同一个位置。

题目描述

突然,你收到从指挥部发来的信息,敌军的轰炸机正朝着你所在的独木桥飞来!为了安全,你的部队必须撤下独木桥。独木桥的长度为 L,士兵们只能呆在坐标为整数的地方。所有士兵的速度都为 1,但一个士兵某一时刻来到了坐标为 0 或 L+1 的位置,他就离开了独木桥。

每个士兵都有一个初始面对的方向,他们会以匀速朝着这个方向行走,中途不会自己改变方向。但是,如果两个士兵面对面相遇,他们无法彼此通过对方,于是就分别转身,继续行走。转身不需要任何的时间。

由于先前的愤怒,你已不能控制你的士兵。甚至,你连每个士兵初始面对的方向都不知道。因此,你想要知道你的部队最少需要多少时间就可能全部撤离独木桥。另外,总部也在安排阻拦敌人的进攻,因此你还需要知道你的部队最多需要多少时间才能全部撤离独木桥。

输入格式

第一行共一个整数 L,表示独木桥的长度。桥上的坐标为 1,2,⋯ L。

第二行共一个整数 N,表示初始时留在桥上的士兵数目。

第三行共有 N 个整数,分别表示每个士兵的初始坐标。

输出格式

共一行,输出 2 个整数,分别表示部队撤离独木桥的最小时间和最大时间。2 个整数由一个空格符分开。


解题思路:

这个题看似显得很累赘,但是做过此类型题的一眼就能看穿,在《挑战程序设计竞赛》这本书上就有详细的解释,当然它们是蚂蚁过桥为背景。解这题的关键在于最大值的求解,我们知道最小值就是在独木桥两边的士兵直接往两端走就可以,走左边还是右边min一下,因为要求所有部队通过所以在所有值里面去一个最大值。对于最大时间的求解,那么我就让靠近左边的人往右边走,靠经右边的人往左边走,如果两个人碰头时,它们可以交换灵魂继续前进,这是《挑战程序设计竞赛》上思想,意思就是我变成他继续前进,他变成我继续前进,最后是对结果没有影响的。那么最大时间就是在最大值里面取一个最大值。

综上所述,最小时间是最小值里面的最大值,最大时间是最大值里面的最大值。


AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int N=5e3+5;
int n,l,x;
int a[N];
int main(){cin>>l>>n;for(int i=0;i<n;i++){cin>>a[i];}sort(a,a+n);//先排序int minx=0;int maxx=0;for(int i=0;i<n;i++){minx=max(min(a[i],l+1-a[i]),minx);//最小时间maxx=max(maxx,max(a[i],l+1-a[i]));//最大时间}cout<<minx<<" "<<maxx<<endl;return 0;
}

例题三: 

AcWing 507. 积木大赛

题目:

春春幼儿园举办了一年一度的“积木大赛”。

今年比赛的内容是搭建一座宽度为 n 的大厦,大厦可以看成由 n 块宽度为 1 的积木组成,第 i 块积木的最终高度需要是 hi。

在搭建开始之前,没有任何积木(可以看成块高度为 0 的积木)。

接下来每次操作,小朋友们可以选择一段连续区间 [L,R],然后将第 L 块到第 R 块之间(含第 L 块和第 R 块)所有积木的高度分别增加 1。

小 M 是个聪明的小朋友,她很快想出了建造大厦的最佳策略,使得建造所需的操作次数最少。

但她不是一个勤于动手的孩子,所以想请你帮忙实现这个策略,并求出最少的操作次数

输入格式

输入包含两行,第一行包含一个整数 n,表示大厦的宽度。 

第二行包含 n 个整数,第 i 个整数为 hi。

输出格式

仅一行,即建造所需的最少操作数。

数据范围

1≤n≤105,
0≤hi≤10000

输入样例:
5
2 3 4 1 2
输出样例:
5

解题思路:

这可不是一道纯正的贪心,因为读完题就知道是差分了,但是为什么还要归到贪心里面,因为贪心是一种思想,上面三个题目都涉及到了最大、最小,一般这种就有贪心思想了,当然,这一个题,会了差分就迎刃而解了,具体的贪心还是体现在算法操作上,比如这个题中间的数最大,那么每次选择区间加一都尽量选上这个数,这样可以使操作次数最小。


AC代码:
#include<iostream>
using namespace std;
int n,ans;
const int N=1e5+5;
int h[N];
int main(){cin>>n;for(int i=1;i<=n;i++){cin>>h[i];}for(int i=n+1;i>=1;i--){h[i]=h[i]-h[i-1];//差分数组}for(int i=1;i<=n+1;i++){if(h[i]>0){ans+=h[i];}}cout<<ans<<endl;return 0;
}

其他例题:

第十四届蓝桥杯省赛大学C组(C/C++)三国游戏_c语言三国游戏-CSDN博客

AcWing 4262. 空调(每日一题)-CSDN博客

AcWing 1262. 鱼塘钓鱼(每日一题)-CSDN博客

AcWing 505. 火柴排队(每日一题)-CSDN博客


相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • CANopen 控制多台设备的支持能力与定制方案评估
  • Cisco交换机SSH使用RSA公钥免密登录(IOS与Nexus,服务器以RHEL8为例)
  • Java线程池练习
  • Visual Studio Code安装与C/C++语言运行(下)
  • 1章4节:数据可视化, R 语言的静态绘图和 Shiny 的交互可视化演示(更新2024/08/14)
  • 数据结构---双向循环链表
  • elementplus 二次封装 select 自定义指令上拉加载更多 完美解决 多次接口调用 重新加载数据多次调用数据!!!
  • LeetCode-字母异位词分组
  • 用R语言进行数据类型的检查和基础转换
  • 如果将一个对象赋值给 ref,那么这个对象将通过 reactive() 转为具有深层次响应式的对象。这也意味着如果对象中包含了嵌套的 ref,它们将被深层地解
  • rk3568-linux sdk编译update.img时以当前时间进行命名
  • 前端开发有什么专业术语吗?
  • Golang | Leetcode Golang题解之第335题路径交叉
  • Android 12系统源码_多屏幕(二)模拟辅助设备功能开关实现原理
  • SecureCRT for Mac/Win:安全高效的专业终端SSH工具软件
  • Angular 4.x 动态创建组件
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • Fabric架构演变之路
  • HomeBrew常规使用教程
  • k8s 面向应用开发者的基础命令
  • Mysql数据库的条件查询语句
  • Redis 中的布隆过滤器
  • spark本地环境的搭建到运行第一个spark程序
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • SwizzleMethod 黑魔法
  • v-if和v-for连用出现的问题
  • Wamp集成环境 添加PHP的新版本
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 你不可错过的前端面试题(一)
  • 一、python与pycharm的安装
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • #QT(串口助手-界面)
  • #QT项目实战(天气预报)
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (Java数据结构)ArrayList
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (十)Flink Table API 和 SQL 基本概念
  • (一)基于IDEA的JAVA基础1
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转载)从 Java 代码到 Java 堆
  • (自用)网络编程
  • .CSS-hover 的解释
  • .naturalWidth 和naturalHeight属性,
  • .Net 4.0并行库实用性演练
  • .net FrameWork简介,数组,枚举
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .sdf和.msp文件读取