贪心算法活动选择问题(递归&&迭代)


#include "stdafx.h"
#include<stdio.h>
#define n 11
int s[n + 1] = { -1,1,3,0,5,3,5,6,8,8,2,12 };                                                 //活动按结束的时间递增排列
int f[n + 1] = { 0,4,5,6,7,8,9,10,11,12,13,14 };
int RECURSIVE_ACTIVITY_SELECTOR(int *s,int *f,int i,int j)         //S[i][j]是所有与a[i],a[j]兼容的活动,f[i]是活动i的结束时间,i,n是下标,s[i]表示i活动开始的时间
{   
    int m = i+1 ;                               
    while (m <= n && s[m] < f[i])                                     //这里一开始i=1的话m=2 在比较s[2]和f[1]就会漏掉一个,所以把主函数里面i的位置都减掉一
    {
        m = m + 1;

    }
    if (m <= n)
    {
        printf("a[%d]   ", m);
        return RECURSIVE_ACTIVITY_SELECTOR(s, f, m, n);

    }
    else
        return 0;
}

int GREEDY_ACTIVITY_SELECTOR(int *s, int *f)
{

    int i = 1,m;
    printf("a[%d]", 1);           //前面有推论结束时间最早的一个一定是最大活动里面的一个选择,结束时间按递增排序,所以a1一定会被输出
    for (m = 2; m <= n; m++)
    {
        if (s[m] >= f[i])
        {
            printf("a[%d]    ", m);
            i = m;                              //每次递归或者迭代都是在上一次调用的结束时间基础上选择下一次调用的开始时间
        }

    }
    return 0;
}

int main()
{
    RECURSIVE_ACTIVITY_SELECTOR(s, f, 1-1, n);  
    printf("\n");
    GREEDY_ACTIVITY_SELECTOR(s, f);
    return 0;
}

最后再附加个动态规划版本吧,我自己没有写出来,哭~。跟前面的最优二叉搜索树的思想很一致,但是要有输出,要去配下标就不会写了,写了也运行不出来,参照导论的伪码也遇到两个问题,一个是下标问题,不知道它怎么定义的数组,一个是输出问题,看了导论的伪码我不知道怎么才能输出来呀~~~它又写了一个表在维护,好心累。抄了个别人写的C++版本,我改成C了,这位博主思维很开阔哦—————>https://blog.csdn.net/luoshixian099/article/details/46559737
参照这两个问题,我在看别人代码的时候都不喜欢看那种片段性质的,只给一个函数,其他不给。这和书上的伪代码有什么区别啊,我自己也能搞出来呀,但是,但是,要把他跑出来是两码事呀,so….我自己上传的代码全都是完整的版本,而且都是自己跑过了的。

#include "stdafx.h"
#include<stdio.h>
void Dynamic_Activity_Selector(int *s, int *f, int length)    //动态规划算法
{
    int c[13][13];

    for (int i = 0; i<=length; i++)    //初始化数组。当i>j时,c[i][j]为空集
    {
        for (int j = 0; j <= length; j++)
        {
            c[i][j] = 0;
        }
    }
    int max = 0;
    for (int j = 1; j <= length; j++)    //自底向上填写表c[i][j]
    {
        for (int i = j - 1; i >= 0; i--)                                //为什么要倒着来呢,从0开始i++的话一开始就能得到11然后不会有k大于max=11,只会输出一个数
        {
            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 > max)   //逐个输出 得到最大兼容子集
                        {
                            max = k;
                            printf("%d\n", k);
                        }
                    }

                }
            }

        }
    }
}
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,8,9,10,11,12,13,14 ,100};
    int length = sizeof(s) / sizeof(s[0]) - 1;
    Dynamic_Activity_Selector(s, f, length);
    return 0;
}

动态规划这东西,每次开一两个二维数组写一张表,还要不断维护,里面嵌套三个for循环,复杂度都到三次方了,还那么难写。。。。。。不过思想很精妙倒是真的。

猜你喜欢

转载自blog.csdn.net/alike_meng/article/details/82558449