Greedy Algorithms(贪心算法)

Topics:

  • Activity-selection problem
  • Elements of the greedy strategy
  • Huffman coding

Greedy Method
For many optimization problem, Dynamic
Programming is overkill. A greedy algorithm always make the choice that looks best at every step. That is, it makes local optimal solution in the hope that this choice will lead to a globally optimal one.(有些问题使用动态规划求最优解有些大材小用了,而且也比较麻烦,低效)

Activity-Selection Problem

问题描述:
在这里插入图片描述
即就是对于两个活动ai和aj满足[si,fi)和[sj,fj)不重叠,则称他们是兼容的。我们的目标是寻找最大兼容的活动集。
Solution:

  1. Sort activities by finish times (let a1, a2,…,an denote sorted sequence)
  2. Pick first activity a1
  3. Remove all activities with start time before finish time of a1
  4. Recursively solve problem on remaining activities

Activity Selection
在这里插入图片描述
(mutually compatible:相互兼容的)
在这里插入图片描述
在这里插入图片描述
子问题:构造一个在ai结束后开始,在aj开始前结束的最大兼容集合。令sij表示在ai结束后开始,且
在aj开始前结束的所有活动的集合。
Property(性质) of Sij
在这里插入图片描述
性质1:
在这里插入图片描述
Optimal Substructure
在这里插入图片描述
最优解包含ak,所以获得两个子问题,寻找Sik中的兼容活动和Skj中的兼容活动。令Aik=Aij∩Sik和Akj=Aij∩Skj,所以就有Aij=Aik ∪{ak} ∪ Akj。

A recursive solution
Define c[i,j] as the number of activities in a maximum-size subset of mutually compatible activities. Then:
在这里插入图片描述
这里我们很容易想到用自底向上的动态规划,但是还有一种更为简化的贪心算法。
Greedy choice property(贪心选择性质)
定理16.1:
在这里插入图片描述
am在Sij的某个最大兼容活动子集中。
在这里插入图片描述
(disjoint:不相交的)
在这里插入图片描述
由此可见,我们可以反复选择最早结束的活动,保留与此活动兼容的活动。重复这一过程,直至不再有剩余活动。贪心算法通常都是这样自顶向下的设计:做出一个选择,然后求解剩下的那个子问题,而不是自底向上地求解出很多子问题,然后再作出选择。

A recursive greedy algorithm
在这里插入图片描述
数组s和f表示活动的开始和结束时间,i指出要求解的子问题Si,以及问题的规模j。

int a[50],x=1;
void RECURSIVE_ACTIVITY_SELECTION(int s[],int f[],int i,int j)//O(n lgn)
{
    int m=i+1;
    while(m<=j&&s[m]<f[i])
    m++;
    if(m<=j)
    {
        a[x++]=m+1;
        RECURSIVE_ACTIVITY_SELECTION(s,f,m,j);
    }
}

An iterative greedy algorithm
在这里插入图片描述

int a[50],x=1;

void ITERATIVE_ACTIVITY_SELECTION(int s[],int f[],int i,int j)//Θ(n)
{
    for(int m=1;m<=j;m++)
    {
        if(s[m]>=f[i])
        {
            a[x++]=m+1;
            i=m;
        }
    }
}

何时使用贪心算法?
How can one tell if a greedy algorithm will solve a particular optimization problem. There is no way in general. If we can demonstrate the following properties, then it is probable to use greedy algorithm:

  • Greedy-choice property
  • Optimal substructure (the same with that of dynamic programming)

Review
在这里插入图片描述

  1. 将最优化问题转化成这样的形式:对其做出一次选择后,只剩下一个子问题需要求解。
  2. 证明做出贪心选择后,原问题总是存在最优解,即贪心选择总是安全的。
  3. 证明做出贪心选择后,剩余的子问题满足性质:其最优解与贪心选择组合即可得到原问题的最优解,这样就得到了最优子结构。

Elements of Greedy Strategy

在这里插入图片描述
Greedy-choice property(贪心选择性质)
我们可以通过做出局部最优(贪心)选择来构造全局最优。换句话说,当进行选择时,我们直接做出在当前问题中看来最优的选择,而不必考虑子问题的解。
Optimal substructure(最优子结构)
将子问题的最优解与贪心选择组合在一起就能生成原问题的最优解。

Knapsack Problem(背包问题)
0-1背包问题与分数背包问题:
在这里插入图片描述
Optimal Substructure
在这里插入图片描述
0/1 Knapsack Example
在这里插入图片描述
Fractional Knapsack
在这里插入图片描述

void GREEDY_KNAPSACK(double p[],double w[],int W,int n,double x[])//p:价格数组;w重量数组;W:背包容量;n:问题规模;x:结果数组
{
    int c=W,i=0;//背包剩余容量
    for(;i<n;i++)
    {
        if(w[i]<c)
        {
            x[i]=1;
            c=c-w[i];
        }
        else
        break;
    }
    if(i<n)
    x[i]=c/w[i];
}

Optimal Substructure (0/1 sack)

在这里插入图片描述
在这里插入图片描述
表达式如下:
在这里插入图片描述
在这里插入图片描述

int c[50][50];
void DYNAMIC_PROGRAMMING_FOR_01_KNAPSACK(int v[],int w[],int n,int W)//v:价值数组;w:重量数组;n:问题规模;W:容量。
{
    for(int x=0;x<=W;x++)
    c[0][x]=0;
    for(int i=1;i<=n;i++)
    {
        c[i][0]=0;
        for(int x=1;x<=W;x++)
        {
            if(w[i]<=x)
            {
                if(v[i]+c[i-1][x-w[i]]>c[i-1][x])
                c[i][x]=v[i]+c[i-1][x-w[i]];
                else
                c[i][x]=c[i-1][x];
            }
            else
            c[i][x]=c[i-1][x];
        }
    }
}

在这里插入图片描述

Huffman codes
在这里插入图片描述
Example of Data Compression
在这里插入图片描述
在这里插入图片描述
Example of Huffman codes
在这里插入图片描述
在这里插入图片描述
Algorithm of Huffman Coding
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值