算法设计学习笔记(四)

本文介绍了贪心算法在区间调度、最小延迟调度、最优高速缓存、最短路径、最小生成树等问题中的应用。贪心算法通过每一步选择局部最优解来逼近全局最优解,如选择最早结束的区间、最早截止时间的任务等。文章详细阐述了各个问题的解决方案,分析了算法的正确性和效率,并讨论了实际操作中的优化策略,如最近最少使用原则(LRU)和逆向删除算法。
摘要由CSDN通过智能技术生成

贪心算法

目录

贪心算法

一、区间调度问题(贪心算法领先)

二、最小延迟调度(一个交换论证)

三、最优高速缓存(一个更复杂的交换)

四、一个图的最短路径

五、最小生成树问题

六、聚类

七、Huffman码与数据压缩

八、最小费用有向树:一个多阶段贪心算法


一、区间调度问题(贪心算法领先)

1. 区间调度问题

       有标记为1,2,……,n的n个需求,每个需求 i 由开始时间s(i)和结束时间f(i)指定,如果没有两个需求在时间上重叠,我们就说需求的子集是相容的。我们的目标是接受一个最大的相容子集,也叫最优子集。

2.设计贪心算法

基本思想:是用一个简单的规则来选择第一个需求 i_{1},一旦接受了需求 i_{1},我们就拒绝与 i_{1} 不相容的需求,然后选择下一个被接受的需求 i_{2} ,拒绝与 i_{2} 不相容的需求,按这种方式走完所有需求。

决定规则:

       1.接受最早开始的需求,则可能拒绝一大批较短时间区间的需求,如图a。

       2.接受最小时间区间的需求,则最短的区间可能阻止我们接受其他构成最优解的区间,如图b。

       3.接受有着最少不相容个数的需求,即选择最少“冲突”的区间,虽然可以在图b的例子中获取最优解,但在图c的例子中,则仅接受了第二行中间的需求,拒绝了最优解,因此这个规则也不可取。

       4.接受最早结束的需求。能够保证我们的资源尽可能早的被释放。

具体算法:

              初始 令R是所有需求的集合,设A为空

              While R 不空

                     选择一个有最早结束时间的需求i∈R

                     把i加到A中

                     从R中删除与需求i不相容的所有需求

              Endwhile

              返回集合A作为被接受的需求集合

3.分析算法

证明算法的正确性

A={i_{1},i_{2},\begin{matrix}...\end{matrix},i_{k}} 是算法返回的集合,O={j_{1},j_{2},\begin{matrix}...\end{matrix},j_{m}}是一个最优的区间集合。

证明思想:证明贪心算法“领先”于这个解O。

       命题4.1 A是一个相容的需求集。

       命题4.2 对所有的指标r≤k,我们有 f(i_{r})<f(j_{r})

       定理4.3 贪心算法返回一个最优的集合A    。

算法的实现

n = 0
start = []
end = []

R = [] #所有的集合
A = [] #被接受的集合

def getinterval():
    n = int(input())
    start = [int(n) for n in input().split()]
    end = [int(n) for n in input().split()]
    for i in range(n):
        R.append([start[i],end[i]])

def interval():
    n = len(R)
    a = 0 #被接受的集合总数
    t = 0 #时间
    for i in range(n):
        if t<R[i][0]:
            a+=1
            A.append([R[i][0],R[i][1]])
            t = R[i][1]
    print('最多工作%d项工作'%a)
    print(A)

getinterval()
interval()

算法的运行时间

O(nlogn)

4. 调度所有的区间问题(多区间调度)

目标:把所有的区间划分到多个资源。

命题4.4 在任何区间划分的实例中,资源数必须至少是区间集合的深度。

具体算法:

              任意打破区间的并列,根据开始时间对他们排序

              设 {I_{1},I_{2},\begin{matrix} & ... & \end{matrix},I_{n}} 表示按这个次序排列的区间

              For j =1,2,3,……,n

                     For 每个按照上述次序领先于 I_{j} 并且与它重叠的区间 I_{i}

                            从对Ij的考虑中排除 I_{i} 的标签

                     Endfor

                     If在{1,2,……,d}中存在任何还没有被排除的标签 then

                            分配一个没排除的标签给 I_{j}

                     Else

                            保留 I_{j} 不分配标签

                     Endif

              Endfor

分析算法:

命题4.5 如果我们使用上述贪心算法,每个区间将被分配一个标签,且没有两个重叠的区间接受同样的标签。

命题4.6 上述贪心算法使用与区间集合深度等量的资源为每个区间安排一个资源,这是所需资源的最优数量。

算法的实现:

 #R为所有区间,r为标签
def intervalall():
    n = len(R)
    t = 0 #time
    s = 0 #endtime
    num = 0 #资源数
    for j in range(n):
        if r[j]!=0:continue
        else:
            num+=1
            r[j] = num
            t = R[j][1]
            for i in range(n):
                print(t,R[i][0])
                if (t<R[i][0])and(r[i]==0):
                    r[i] = num
                    t = R[i][1]
        print(r)
    print(num)
    print(r)

二、最小延迟调度(一个交换论证)

1. 最小延迟调度问题

       现有单一资源和一组使用资源的n个需求,每个需求需要一个时间区间,每一个需求i有一个截止时间 d_{i} ,并且它要求一个长为 t_{i} 的连续的时间区间(即区间长度为 t_{i},他想被安排在截止时间之前的任何时刻,每个被接受的需求必须被分配一个长为 t_{i} 的时间区间,且不同的需求被分在不重叠的区间。

2. 设计算法

       最早截止时间优先,具有最早截止时间的任务完成得更早一些。

具体算法:

       按照它们的截止时间的次序对任务排序

       为使符号简单,假定 {d_{1}\begin{matrix}\leq ... \leq\end{matrix}d_{n}}

       初始f=s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值