04-贪心

贪心

能采用贪心算法求最优解的问题,一般具有的重要性质为:最优子结构性质贪心选择性质

贪心选择性质是指问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来得到,这是贪心法和动态规划法的主要区别。

贪心法的求解过程:

  1. 把求解的问题分成若干个子问题
  2. 对每个子问题求解,得到子问题的局部最优解
  3. 把子问题的解局部最优解合成原来解问题的一个解

虽然贪心法每一步都能获得局部最优解,但由此产生的全局解有时不一定是最优的。

活动安排问题

设有n个活动的集合E= \{ 1,2,..,n \},其中每个活动都要求使用同一资源,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si<fi。如果选择了活动i,则它在时间区间[si,fi]内占用资源。若区间[si,fi]与区间[sj,fj]不相交,则称活动i与活动j是相容的。活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合。

活动安排问题的贪心选择策略:每次选择最早结束的

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

@Data
@AllArgsConstructor
class Activity {
    int id;
    int start;
    int end;
    boolean selected;
}

public class Greedy {
    // 贪心法解决活动安排问题,返回最多安排的活动数
    public static int greedySelection(List<Activity> activities) {
        // 以活动最早结束时间作为贪心选择策略
        activities.sort(((o1, o2) -> {
            if (o1.start == o2.start)
                // 如果开始时间相同,则按结束时间从早到晚排序
                return o1.end - o2.end;
            // 先按活动开始时间从早到晚排序
            return o1.start - o2.start;
        }));
        // 初始选择安排活动0
        activities.get(0).selected = true;
        // 最近一次安排的活动序号
        int prev = 0;
        // 一共安排了几个活动
        int count = 1;
        for (int i = 1; i < activities.size(); i++) {
            // 如果第i个活动与最近一次安排的活动相容,则安排第i个活动
            if (activities.get(i).start >= activities.get(prev).end) {
                activities.get(i).selected = true;
                prev = i;
                count++;
            } else { // 不相容
                activities.get(i).selected = false;
            }
        }
        return count;
    }

    public static void main(String[] args) {
        List<Activity> activities = new ArrayList<>();
        activities.add(new Activity(4, 0, 2, false));
        activities.add(new Activity(2, 1, 3, false));
        activities.add(new Activity(1, 3, 6, false));
        activities.add(new Activity(3, 5, 9, false));
        activities.add(new Activity(5, 7, 9, false));
        activities.add(new Activity(7, 9, 11, false));
        activities.add(new Activity(6, 9, 12, false));
        activities.add(new Activity(8, 12, 14, false));
        System.out.println(greedySelection(activities));
        for (Activity activity : activities) {
            if (activity.selected)
                System.out.println(activity);
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • # 引例 —— 钱币找零问题 贪心算法的思想非常简单且算法效率很高,在一些问题的解决上有着明显的优势。 假设有3种...
    Tenloy阅读 4,463评论 0 3
  • 贪心算法: 在对问题求解时,总做出当前看来最好的选择,即求“目光短浅”的局部最优,是一种近似最优解,而不是从整体考...
    _属于我阅读 4,635评论 0 3
  • 一、基本思想 贪心算法采用每一步都选取当前状态下最优的选择,这样虽然能得到局部最优解,但是可能无法求得全局最优解。...
    无问o阅读 5,439评论 0 2
  • 背景 有1元、5元、10元、20元、100元、200元的钞票无穷多张。现使用这些钞票支付X元,最少需要多少张? 例...
    程序员姜戈阅读 3,996评论 0 0
  • 1. 贪心算法定义[1] 贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,...
    是培根不是培根阅读 4,231评论 0 0