贪心算法

来源:互联网 发布:中国知网 知乎 编辑:程序博客网 时间:2024/06/07 01:23

1.贪心算法定义
贪心算法求解问题时,在每一步都采用当时看起来的最佳选择,它总是作出局部最优选择。决策一旦作出,就不可再更改。这个局部最优决策依照的标准称为贪心准则。

2.贪心算法求解问题的前提条件
(1)贪心选择性质
在求解一个问题的过程中,如果每一个阶段的选择都是当前状态下的最优选择,即局部最优选择,并且最终能够求得问题的整体最优解,则该问题可以通过贪心选择来求解,这时就说此问题具有贪心选择性质。
(2)最优子结构性质
当一个问题的最优解包含了这个问题的子问题的最优解,就说这个问题具有最优子问题结构。

3.贪心算法与动态规划
动态规划每一次选择都依赖于子问题的解。采用自底向上的方式求解,先求解较小的子问题,然后是较大的子问题。因此,动态规划要先求解子问题才能进行第一次选择。
贪心算法是自顶而下求解的。先作出当前看来最佳的选择,然后求解剩下的唯一的子问题。贪心算法在第一次选择之前不需要求解任何子问题。

4.例子

4.1 活动安排问题
有n项活动需要使用同一个会场,任意两个活动不能同时使用这个会场。每个活动都有一个开始时间si和结束时间fi,活动i占用会场的时间是[si,fi)。如果两个活动[si,fi)和[sj,fj)的区间不相交,则活动i和活动j能够在同一会场的不同时间段进行。我们的目的是通过贪心算法使得尽可能多的活动可以在会场中进行。假设活动已经按照结束时间的单调递增顺序排序。
f1≤f2≤f3≤…≤fn
活动集S如下:
这里写图片描述
解题思路:将活动1安排在第一个执行,找到活动1结束后最先开始的活动作为第二个活动,依次类推,直到没有活动可以选择。用数组flag[n]存储解向量,如果活动i被选择,则flag[i]=true,否则flag[i]=false。
Java代码:

import java.util.*;public class 活动选择问题 {    static boolean flag[]=new boolean[11];//活动是否被选择    public static void main(String[] args) {        int[] s={1,3,0,5,3,5,6,8,8,2,12};//开始时间        int[] f={4,5,6,7,9,9,10,11,12,14,16};//结束时间        GreedySelecter(s, f);        for(int i=0;i<11;i++){            if(flag[i])                System.out.print(i+1+" ");        }    }    //贪心选择    private static void GreedySelecter(int[] s,int[] f){        int n=s.length;        int j=0;        flag[0]=true;        for(int i=1;i<n;i++){            if(s[i]>=f[j]){                flag[i]=true;                j=i;            }        }    }}