第十六章 贪心算法

来源:互联网 发布:山人教育模型源码 编辑:程序博客网 时间:2024/05/19 23:18

def:贪心算法是一种以局部最优最优选择以期求得全局最优解得算法。

16.1活动选择问题

求一个活动选择问题的域中求最大兼容活动子集。

活动选择问题具有最优子结构:解中若包含活动ak,s.t. S[...k]和S[k+1...]都为最大兼容活动子集

若用c[i,j]来表示S[i...j]的大小则有递归公式:



由此可以通过动态规划方法求解活动选择问题的最优解。

若注意到此问题的一个性质,则可以只需要遍历一遍所有活动采用贪心选择而求得最优解。


贪心选择的是S中结束时间最早的活动。实现如下:

"""    因为 f由小到大排序,所以必然包含第一个活动"""def RECURSIVE_ACTIVITY_SELECTOR(s, f, k, n):    m = k + 1    while m < n and s[m] < f[k]:        m = m + 1    if m < n:        ai = [m]        a = RECURSIVE_ACTIVITY_SELECTOR(s, f, m, n)        if a != None:            ai.extend(RECURSIVE_ACTIVITY_SELECTOR(s, f, m, n))        return ai    else:        return Nonedef GREEDY_ACTIVITY_SELECTOR(s,f):    n = len(s)    a = [1]    k = 1    for m in range(2, n):        if s[m] >= f[k]:            a.append(m)            k = m    return a        if __name__ == "__main__":    s = [0,1,3,0,5,3,5,6,8,8,2,12]    f = [0,4,5,6,7,9,9,10,11,12,14,16]    a = RECURSIVE_ACTIVITY_SELECTOR(s,f,0, len(s))    print(a)    a = GREEDY_ACTIVITY_SELECTOR(s, f)    print(a)


16.2贪心算法原理

所有的贪心算法问题都有一个对应的动态规划解法。对含有某些特性的动态规划问题,我们用贪心策略,每一步求局部的最优解而最后得到一个最优解。为了保证可以实施贪心策略和贪心算法正确我们需要证明以下三点:


贪心选择性质:对比与动态规划问题我们总是依赖子问题的最优解来构造出问题的最优解,而贪心选择只考虑局部最优,而不依赖于子问题的解。故贪心算法由上而下的分解子问题,而动态规划算法由底向上的求解所有子问题。

所以我们必须要证明局部最优能生成全局最优解,既将问题分解为一个局部最优解和包含最优解的子问题。

通过以上分析0-1背包问题不可以使用贪心算法求解,而分数背包问题可以是用贪心算法求解。


16.3赫夫曼编码

对于定长编码的文件的压缩,使用变长编码既使用短编码表示出现概率高的字符,使用长编码表示出现概率低的字符,以取得对定长编码的优势。为了保证编码的唯一性,我们使用前缀码的特性来简化编解码的过程。文件的最优编码方案就是一棵满二叉树,优于非满二叉树的定长编码:



我们使用HUFFMAN来构造满二叉树:



此过程中使用贪婪策略每次以集合中概率最低的两个对象作为叶子构造一棵子树,通过如下两个引理证明贪心策略有效:







16.4 拟阵和贪心算法



加权的拟阵,可以用贪心算法求解,求解与正确性的证明如下(其实就是动态规划原理中的剪切-粘贴技术证明和定义)







16.5用拟阵求解任务调度问题



def QUICKSORT(A, p, r):    if p < r:        q = PARTITION(A, p, r)        QUICKSORT(A, p, q-1)        QUICKSORT(A, q+1, r)def PARTITION(A, p, r):    x = A[r][1][0]    i = p    for j in range(p, r):        if A[j][1][0] <= x:            temp = A[i]            A[i] = A[j]            A[j] = temp            i = i + 1    temp = A[i]    A[i] = A[r]    A[r] = temp    return idef SCHEDULED(S):    A = []    B = []    for i in range(0, len(S)):        A.append(S[i])        n = len(A)        if n > A[n-1][1][0]:            m = 0            w = A[0][1][1]            for j in range(1, n):                if A[j][1][1] < w:                    m = j                    w = A[j][1][1]            b = A.pop(m)            B.append(b)    return A, Bif __name__ == "__main__":    S = [(1,(4,70)), (2,(2,60)), (3,(4,50)), (4,(3,40)), (5,(1,30)), (6,(4,20)), (7,(6,10))]    QUICKSORT(S, 0, len(S)-1)    print(S)    A,B = SCHEDULED(S)    print(A)    print(B)

习题解答


0 0
原创粉丝点击