• 活动选择问题(动态规划和贪心算法)


    有一个由n个活动组成的集合S = {a1, ..., an}

        1. 这些活动使用同一个资源,而这个资源在某一时刻只供一个活动使用

        2. 每个活动都有一个开始和结束时间si/fi;如果被选中,则任务ai发生在半开时间区间[si, fi)

        3. 如果两个活动ai和aj不重叠,则称两个活动兼容

         活动选择问题,希望选出一个最大兼容活动集

        假设活动已经按结束时间递增排好序

    最优子结构

        Sij表示在ai结束之后,aj开始之前结束之前的活动集合;Aij表示Sij的一个最大兼容活动集

        假设Aij包含ak, 则得到两个子问题,寻找Sik以及Skj的最大兼容活动集

        用c[i, j]表示集合Sij的最优解的大小,则可得递归式:c[i, j] = c[i, k] + c[k, j] + 1

        从而实际上

        c[i, j] = 0    if Sij = 空集

                    max{c[i, k] + c[k, j] +1}    ak属于Sij

    活动选择问题的另一个性质,使得无须求解所有子问题就可以选择出一个活动加入到最优解;选择的标准为,选出活动后剩下的资源应能被尽量多的其他任务所用 【选择最早结束的活动】

    定理可以证明:任意非空子问题Sk,am是Sk中结束时间最早的活动,则am在Sk的某个最大兼容活动子集中【 假设一个最大兼容活动子集Ak,用am替代Ak中最早结束的活动得到Ak',依然是最大兼容活动子集】

    ——>贪心算法,自顶向下的设计,做出一个选择,然后求解剩下的那个子问题,而不像动态规划自底向上地求解很多子问题,然后再做出选择

    假设已经按照活动结束时间排好序

    递归贪心算法:

    RECURSIVE-ACTIVITY-SELECTOR(s, f, k, n)             // s表示活动的开始时间数组;f表示结束时间数组;k表示上一个选中的活动,初始为0【引入a[0],其结束时间为0】;n为问题规模

        m = k + 1

        while(m<=n && s[m] < f[k])         //活动必须在活动集合中;且其开始时间必须比上一个活动的结束时间晚

            m = m + 1

        if m<=n

            return a[m] 并上  RECURSIVE-ACTIVITY-SELECTOR(s, f, m, n)

        else

            return 空集

    迭代贪心算法:(通常“尾递归”的算法都可以很直接的转化为迭代形式)

    GREEDY-ACTIVITY-SELECTOR(s, f)

        n = s.length

        A = {a1}

        k = 1

        for m = 2 to n

            if(s[m] >= f[k])

                A = A 并上 {am}

                k = m

        return A

  • 相关阅读:
    Springboot整合AOP实现日志的保存
    Linux | 进程间通信 | system V共享内存 | 介绍和使用
    C++对象间通信组件,让C++对象“无障碍交流”
    Triton部署Torch和Onnx模型
    Centos7 安装 Etcd
    【OpenCv】相机标定介绍及python/c++实现
    【2023秋招笔经】20220813 16点美团笔试
    vite的学习笔记
    javaee实验,SpringMVC 参数绑定
    Python学习笔记--类的定义和调用
  • 原文地址:https://blog.csdn.net/m0_72431373/article/details/128169097