贪心算法-活动安排问题

1、贪心算法

 (1)原理:在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。

  (2)特性:贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。能够用贪心算法求解的问题一般具有两个重要特性:贪心选择性质和最优子结构性质。

 1)贪心选择性质

 所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素。贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。

 对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。证明的大致过程为:首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明通过每一步做贪心选择,最终可得到问题的整体最优解。其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于利用该问题的最优子结构性质。

 2)最优子结构性质

  当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。

 (3)贪心算法与动态规划算法的差异:

 动态规划和贪心算法都是一种递推算法,均有最优子结构性质,通过局部最优解来推导全局最优解。两者之间的区别在于:贪心算法中作出的每步贪心决策都无法改变,因为贪心策略是由上一步的最优解推导下一步的最优解,而上一部之前的最优解则不作保留,贪心算法每一步的最优解一定包含上一步的最优解。动态规划算法中全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解。

  (4)基本思路:

 1)建立数学模型来描述问题。
 2)把求解的问题分成若干个子问题。
 3)对每一子问题求解,得到子问题的局部最优解。
 4)把子问题的解局部最优解合成原来解问题的一个解。

 2、活动安排问题

 活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子。该问题要求高效地安排一系列争用某一公共资源的活动。贪心算法提供了一个简单、漂亮的方法使得尽可能多的活动能兼容地使用公共资源。
import java.util.Scanner;

public class ActivityArrange {
   static int n;//n个活动
   static boolean a[];//存储结果集合
   static Activity []activities;
    public static void main(String[] args) {
     System.out.println("请输入N个活动\n");
     Scanner scanner=new Scanner(System.in);
      n=scanner.nextInt();

     a=new boolean[n];
     activities=new Activity[n];
     for(int i=0;i<n;i++){
         int a=scanner.nextInt();
         int b=scanner.nextInt();
         Activity activity=new Activity(a,b);
         activities[i]=activity;
     }

     sort(activities);//根据结束时间升序排列


     greedyArrange();//贪心安排

     print();
    }

    private static void greedyArrange() {
       a[0]=true;
       int j=0;//表示上一个,初始化为第一个
       for(int i=1;i<n;i++){
           if(activities[i].start>=activities[j].finish){
               j=i;
               a[i]=true;
           }else {
            a[i]=false;
        }
       }
    }

    private static void print(){
        for(int i=0;i<n;i++){
            if(a[i]){
                System.out.println("开始时间:"+activities[i].start+" 结束时间:"+activities[i].finish);

            }
        }
    }
    private static void sort(Activity[] activities2) {
        for(int i=0;i<activities2.length-1;i++)     
        {
            for(int j=i+1;j<activities2.length;j++)
            {
                if(activities2[i].finish>activities2[j].finish)
                {
                    Activity temp=activities2[i];
                    activities2[i]=activities2[j];
                    activities2[j]=temp;
                }
            }
        }
    }

}
class Activity{

    public  int start;//开始时间
    public     int finish;//结束时间
    public Activity(int start,int finish){
        this.start=start;
        this.finish=finish;
    }
}


输入:
请输入N个活动

11
6 10
3 8
5 9
8 12
2 13
0 6
3 5
8 11
5 7
12 14
1 4

输出:
开始时间:1 结束时间:4
开始时间:5 结束时间:7
开始时间:8 结束时间:11
开始时间:12 结束时间:14

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值