Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 找到我可以参加的课程的最大数量_Algorithm - Fatal编程技术网

Algorithm 找到我可以参加的课程的最大数量

Algorithm 找到我可以参加的课程的最大数量,algorithm,Algorithm,我正试图找到一个最佳的(以复杂性的方式)算法,以获得我可以参加的课程的最大数量。我不在乎课程的总长度,也不在乎课程本身。这一切都是为了尽可能多地参加课程 给定两个数组S和E。S[i]包含课程的开始时间,E[i]包含相应的结束时间。数组已经按E排序了。因为我不是Flash,所以我不能参加第一个数组的结束时间等于下一个数组的开始时间的课程 下面是一个例子: S = [ "2014-11-06 01:00:00", "2014-11-06 03:00:00", "2014-11

我正试图找到一个最佳的(以复杂性的方式)算法,以获得我可以参加的课程的最大数量。我不在乎课程的总长度,也不在乎课程本身。这一切都是为了尽可能多地参加课程

给定两个数组S和E。S[i]包含课程的开始时间,E[i]包含相应的结束时间。数组已经按E排序了。因为我不是Flash,所以我不能参加第一个数组的结束时间等于下一个数组的开始时间的课程

下面是一个例子:

S = [
    "2014-11-06 01:00:00",
    "2014-11-06 03:00:00",
    "2014-11-06 07:00:00",
    "2014-11-06 09:00:00",
    "2014-11-06 09:00:00"
]

E = [
    "2014-11-06 05:00:00",
    "2014-11-06 06:00:00",
    "2014-11-06 08:00:00",
    "2014-11-06 09:00:00",
    "2014-11-06 10:00:00"
]
对于这些值,正确答案为3,因为我可以参加课程1、3和5(也可以进行其他组合)


提前感谢

既然您评论说每门课程都需要全员参与,我想算法可以是这样的:

  • 按S排序课程

  • 如果您加入S1,请查找S>E1的课程列表;若该列表以Sk开头,那个么对(Sk,…,Sn)使用递归,总结果将是(递归的结果)+1

  • 如果跳过S1,则对(S2、S3、…、Sn)及其值使用递归

  • 选择步骤2和步骤3中的最大值

  • UPD(来自注释)我们应该检查的不仅仅是第一步,否则递归应该存储[K-N]集的结果,以免再次计算。我可以想象这样的情况:
    S1,S2,E1,E2,S3,E3。。。。SN,EN
    如果我们不检查[3-N]部分,可以递归计算两次(带S1或不带S1)

    核心思想 其思想是使用递归检查所有课程。蒂莫西·哈的回答解释了基本解决方案。为了清楚起见,我想起来:

  • 按S排序课程
  • 从S1开始:
  • 找到k=min(j,E1
  • 如果k>2(=当前航向+1),则找到S2、…、Sn的最佳拟合
  • 在步骤3和步骤4之间返回最佳拟合
  • 基于动态规划的时间优化 但是您可以通过存储中间值来优化它。为此,我们将从头开始,而不是从头开始递归

    设b是初始化为0的n个整数的数组。设bn=1。最后,设i=n-1

    当i>0时,执行以下操作:

  • 考虑一下我们修的课程。我们必须找到k=min(j,Ei
  • 如果k存在,则bi=max(1+bk,bi+1)
  • 否则,bi=bi+1(我们不必显式地声明“max(1,bi+1)”,因为1≤ bi+1)
  • 减小i并继续执行步骤1
  • 循环结束时,解决方案为b1

    下面是C语言的解决方案

    //我假设S[]是按递增顺序排序的
    //E[]是与S关联的结束时间:
    //(从S[i]开始的课程在E[i]结束)
    int findBestNumber(ADateType S[],ADateType E[],int n){
    int i=n-1,k,res;
    int*sol=NULL;
    如果(!(sol=malloc(n*sizeof(int)))
    返回-1;
    memset(sol,0,sizeof(*sol));
    溶胶[n-1]=1;
    而(i-->0){
    k=findMinIndex(E[i],S);
    如果(k>=0)//k存在
    sol[i]=max(1+sol[k],sol[i+1]);
    否则//k不存在,我们将返回一个类似-1的值
    sol[i]=sol[i+1];
    }
    res=sol[0];
    免费(sol);
    返回res;
    }
    
    findMinIndex(after,S)
    搜索最小索引k,以便在≤ 由于调用此函数时,
    S
    是排序的,因此这是一个简单的二进制搜索。在上面的例子中,如果找不到这样的索引,我认为我们从
    findMinIndex()
    返回了一个负值

    DP版本的空间和时间复杂性 在动态规划版本中,我们只是一步一步地计算中间结果,并且只计算一次。因此,这是O(n)。空间复杂度也是O(n),因为我们需要存储n个中间值

    但请记住,我们必须按开始时间对课程进行排序!使用适当的排序算法(例如合并排序)的此操作为O(n.log(n))。因此,最终的时间复杂度为O(n.log(n))

    奖励:一个可工作的C实现


    注意:在再次阅读问题后,我注意到我无法选择与先前课程结束时间同时开始的课程…要排除这些课程,只需在
    findMinIndex()中打开
    =
    s
    into
    s

    倒数第二个元素对两个都是一样的。你必须坐满每门课吗?或者你可以只在场一点,然后转到另一门课吗?我必须在场,直到课程结束。我认为问题是NP完全问题,你必须通过所有的解决方案才能找到最好的解决方案。尽你最大的努力避免尝试您已经知道不可能的解决方案(子集不可能)您的问题与最大覆盖率问题类似()。贪婪算法似乎本质上是最大覆盖率的最佳多项式时间近似算法。这个问题可能很愚蠢,但我如何决定是否加入S1?第一步有两个选择:是否加入S1。使用递归计算到最后,如果S1的结果更大,则加入:-)我还想到了复杂性,因为它是一个线性扫描(两个并行),沿着课程队列,它应该是O(N)。丹尼尔,如果这个想法是正确的,你会把它转换成代码,对吗?@DanielFreudenberger,你怎么能达到O(N)下的复杂性呢?!你必须处理每一门课程才能做出决定,对吗?我同意,平均而言,但假设你能参与每一门课程,你最终会在每一门课程上执行二分法。当然,您可以使用动态规划降低时间复杂度:)感谢您提到动态规划。维基百科上有一整篇文章列出了“使用动态编程的算法”