五大常用算法(三) - 贪心算法

贪心算法是一种求解局部最优解的方法,适用于部分问题的整体最优解。文章介绍了贪心算法的基本概念,以及通过活动选择问题展示了贪心策略的应用,即每次选择结束时间最早的活动以尽可能多地安排不冲突的活动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

贪心算法

简介

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

贪心算法不是对所有问题都能得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路径问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。由于贪心法的高效性以及其所求得的答案比较接近最优结果,贪心法也可以用作辅助算法或者直接解决一些要求结果不特别精确的问题。
在这里插入图片描述
  
解题的一般步骤是:
  1、 建立数学模型来描述问题;
  2、把求解的问题分成若干个子问题;
  3、 对每一子问题求解,得到子问题的局部最优解
  4、把子问题的局部最优解合成原来问题的一个解。


实例

1. 活动选择问题

有n个需要在同一天使用同一个教室的活动 a1, a2, …, an,教室同一时刻只能由一个活动使用。每个活动 ai 都有一个 开始时间si 和 结束时间fi 。一旦被选择后,活动ai就占据半开时间区间[si,fi)。如果[si,fi]和[sj,fj]互不重叠,ai和aj两个活动就可以被安排在这一天。
该问题就是要安排这些活动使得尽量多的活动能不冲突的举行。例如下图所示的活动集合S,其中各项活动按照结束时间单调递增排序。
  在这里插入图片描述

贪心策略应该是每次选取结束时间最早的活动

用贪心法的话思想很简单:活动越早结束,剩余的时间是不是越多?那我就选择最早结束的那个活动,找到后在剩下的活动中再找最早结束的不就得了?这也是把各项活动按照结束时间单调递增排序的原因。

public class ActiveTime {
   
   
    public static void main(String[] args) {
   
   
        //创建活动并添加到集合中
        List<Active> actives = new ArrayList<Active>();
        actives.add(new Active(1, 4));
        actives.add(new Active(3, 5));
        actives.add(new Active(0, 6));
        actives.add(new
贪心算法(Greedy Algorithm)是一种在每一步选择中都采取当前状态下最优的选择,从而希望最终导致全局最优的算法贪心算法通常有以下特点: 1. 贪心选择性质:每一步都采取最优的选择,即局部最优解。 2. 最优子结构性质:原问题的最优解包含子问题的最优解。 3. 无后效性:每一步的决策只与当前状态有关,与之前的决策无关。 贪心算法可以用来求解一些最优化问题,如最小生成树、背包问题、活动选择问题等。 以活动选择问题为例,假设有n个活动,每个活动有一个开始时间s和结束时间f,多个活动可能在同一时间段内进行,但是同一时间只能进行一个活动。如何选择活动,使得能够安排的活动数量最多? 贪心算法的思路是:按照结束时间从早到晚排序,每次选择结束时间最早的活动,且不与已经选择的活动时间冲突。这是因为选择结束时间最早的活动,可以给后面留下更多的时间选择其他活动,从而使得总的安排活动数量最多。 参考代码如下: ``` #include <iostream> #include <algorithm> using namespace std; struct Activity { int start, finish; }; bool compare(Activity s1, Activity s2) { return (s1.finish < s2.finish); } void printMaxActivities(Activity arr[], int n) { sort(arr, arr+n, compare); cout << "Selected activities:\n"; int i = 0; cout << "(" << arr[i].start << ", " << arr[i].finish << "), "; for (int j = 1; j < n; j++) { if (arr[j].start >= arr[i].finish) { cout << "(" << arr[j].start << ", " << arr[j].finish << "), "; i = j; } } } int main() { Activity arr[] = {{1, 2}, {3, 4}, {0, 6}, {5, 7}, {8, 9}, {5, 9}}; int n = sizeof(arr)/sizeof(arr[0]); printMaxActivities(arr, n); return 0; } ``` 输出结果为: ``` Selected activities: (1, 2), (3, 4), (5, 7), (8, 9), ``` 可以看到,按照贪心算法的思路,选择了4个活动,使得能够安排的活动数量最多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值