码迷,mamicode.com
首页 > 编程语言 > 详细

算法导论--贪心算法与动态规划(活动选择问题)

时间:2015-06-19 13:38:12      阅读:1013      评论:0      收藏:0      [点我收藏+]

标签:算法导论   贪心算法   活动选择   

活动选择问题

有一个教室,而当天有多个活动,活动时间表如下:找出最大兼容活动集!活动已按结束时间升序排序.
技术分享

动态规划

采用动态规划需要满足两个条件:1.最优子结构2.子问题重叠
Sij表示在ai结束后和aj开始前活动的集合,假定Aij为活动集合Sij的最大兼容子集,其中包含活动ak。问题变成求SikSkj最大兼容活动子集AikAkjz。我们用c[i,j]表示Sij的最优解的大小。
则c[i,j] = c[i,k]+c[k,j]+1;最后我们需要遍历所有可能的k值,找出最大的一个划分作为c[i,j],也即有子问题重叠问题。
即可以设计一个自底向上的算法,一步步到整个活动大小!
算法复杂度为O(n3)

void Dynamic_Activity_Selector(int *s,int *f,int length)    //动态规划算法
{
    int c[13][13];              

    for (int m=0;m<12;m++)    //初始化数组。当i>j时,c[i][j]为空集
    {
        for (int n=0;n<=m;n++)
        {
            c[n][m] = 0;
        }
    }                                   
    int imax=0;
    for (int j=1;j<=length;j++)    //自底向上填写表c[i][j]
    {
      for (int i=j-1;i>=0;i--)
      {
          for (int k=i+1;k<j;k++)
          {  
              if (s[k]>=f[i] && f[k] <= s[j]) //检查划分点k是否满足条件
              {   
                  if (c[i][k]+c[k][j]+1 > c[i][j])
                  {   
                    c[i][j] = c[i][k]+c[k][j]+1;

                    if (k > imax)   //逐个输出 得到最大兼容子集
                    {
                        imax = k;
                        cout<<imax<<endl;
                    }
                  }

              } 
          }

      }
    }
}

贪心算法

贪心算法的原理是在作出每个决策时,它在当时(局部)看来是最好的选择。作出一个贪心选择后,要求只剩下一个子问题。令Sk为在ak结束后开始的任务集合。对于活动选择问题,考虑局部最优时,作出一个决策前总是为以后的活动留下更多的时间,选择活动ak后,在Sk中选择最早结束的活动!所以第一次选择时,选择最早结束的活动,即是a1,下一次在S1选择最早结束的活动.。
算法复杂度O(n)

迭代版本

void Greedy_Activity_Selector(int s[],int *f,int length)    //迭代贪心算法
{   
    int *A = new int[length];   //存储最大兼容子集
    if ( A == NULL)
        return;
    int i=0;
    A[i++]=1;
    int n=length;
    int k=1;
    for (int m=2;m<=n;m++)
    {
        if (s[m] >= f[k])
        {
            A[i++]=m;
            k=m;
        }
    }

    for(int j=0;j<i;j++)
        cout<<A[j]<<endl;
    delete []A;
}

完整代码

/************************************************************************
CSDN 勿在浮沙筑高台 
http://blog.csdn.net/luoshixian099
算法导论--贪心算法与动态规划(活动选择问题)
2015年6月18日                 
************************************************************************/
#include <iostream>
using namespace std;
void Recursive_Activity_Selector(int *s,int *f,int k,int n)  //递归贪心算法
{
    int m = k+1;
    while ( (m<=n) && (s[m]<=f[k]))    //选出满足活动的m
        m++;
    if (m <= n)
    {
        cout<<m<<endl;
        Recursive_Activity_Selector(s,f,m,n);//递归
    }
    else
        return;
}

void Greedy_Activity_Selector(int s[],int *f,int length)    //迭代贪心算法
{   
    int *A = new int[length];   //存储最大兼容子集
    if ( A == NULL)
        return;
    int i=0;
    A[i++]=1;
    int n=length;
    int k=1;
    for (int m=2;m<=n;m++)
    {
        if (s[m] >= f[k])
        {
            A[i++]=m;
            k=m;
        }
    }

    for(int j=0;j<i;j++)
        cout<<A[j]<<endl;
    delete []A;
}
void Dynamic_Activity_Selector(int *s,int *f,int length)    //动态规划算法
{
    int c[13][13];              

    for (int m=0;m<12;m++)    //初始化数组。当i>j时,c[i][j]为空集
    {
        for (int n=0;n<=m;n++)
        {
            c[n][m] = 0;
        }
    }                                   
    int imax=0;
    for (int j=1;j<=length;j++)    //自底向上填写表c[i][j]
    {
      for (int i=j-1;i>=0;i--)
      {
          for (int k=i+1;k<j;k++)
          {  
              if (s[k]>=f[i] && f[k] <= s[j]) //检查划分点k是否满足条件
              {   
                  if (c[i][k]+c[k][j]+1 > c[i][j])
                  {   
                    c[i][j] = c[i][k]+c[k][j]+1;

                    if (k > imax)   //逐个输出 得到最大兼容子集
                    {
                        imax = k;
                        cout<<imax<<endl;
                    }
                  }

              } 
          }

      }
    }
}
int main()
{
    int s[]={0,1,3,0,5,3,5,6,8,8,2,12,100};   //s[12]=100是为了动态规划的输出
    int f[]={0,4,5,6,7,9,9,10,11,12,14,16,101};
    int length = sizeof(s)/sizeof(s[0])-1;

    cout<<"Recursive_Activity_Selector:"<<endl;
    Recursive_Activity_Selector(s,f,0,length-1);

    cout<<"Greedy_Activity_Selector:"<<endl;
    Greedy_Activity_Selector(s,f,length-1);

    cout<<"Dynamic_Activity_Selector:"<<endl;
    Dynamic_Activity_Selector(s,f,length);
    return 0;
}

算法导论--贪心算法与动态规划(活动选择问题)

标签:算法导论   贪心算法   活动选择   

原文地址:http://blog.csdn.net/luoshixian099/article/details/46559737

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!