事件(开始,完成),最多1天的事件。 C ++中的性能问题

时间:2019-03-31 06:35:24

标签: c++ optimization

他们给了我N组开始/结束时间,例如:(8:45/12:00)。
返回最大事件数后,一个人可以参加而不会重叠。
(一项活动在8:00结束,另一活动在8:00开始不重叠)。

我为每个事件都做了一个开始和结束的基础课。
之后,我创建了一个递归函数来制作“事件链”。
我的解决方案在N <100的情况下完成了工作,但是因为O(n!)在N> 100的情况下[我认为]我的(非常)旧计算机不能足够快地向我求助。

class Event{
public:
int hh,mm;
int ehh,emm;
};

int chain(Event* array,int nchain,int index,int N){
int max = nchain;
for(int i = 0;i<N;i++){
    if(overlapping(app[index],app[i])){
        int tempmax = chain(array,nchain+1,i,N);
        if(tempmax > max){
            max = tempmax;
        }
    }
}
return max;
}

bool overlapping(Event a,Event b){
    if(a.ehh<b.hh || (a.ehh==b.hh && a.emm<=b.mm) ){
        return true;
    }
    else{
        return false;
    }   
}

2 个答案:

答案 0 :(得分:0)

天真的解决方案可能是O(2 N ),但是:

  1. 当子集具有内部调度冲突时,您似乎有修剪逻辑,这已经极大地帮助了复杂性。

  2. 使用动态编程可以做得更好。这个问题听起来似乎具有很好的控制特征-如果一组N个事件在X时刻让您自由,而另一组N + 1个事件在X时刻或更早的时间内给您N + 1个事件,则前者不需要会被考虑。

    修剪为主的子集,并继续探索最佳边界。

另一个观点(导致使用相同的算法)是,在包括特定事件Y的所有时间表中,选择在Y开始之前做什么和在Y结束之后做什么完全独立。 ,并且可以单独进行优化。

我相信,但没有提供证据,您最终的算法将是O(N 2 )。

答案 1 :(得分:0)

使用贪婪的解决方案可以更好地解决此问题。首先,我们需要按照结束时间从小到大的顺序对事件进行排序。这样,在数组中选择与所选事件集不重叠的下一个事件始终是最佳选择。时间复杂度将为O(nlogn)。

#include<algorithm>
class Event{
    public:
    int hh,mm;
    int ehh,emm;
};

bool overlapping(Event a, Event b){//assumes a,b sorted by finish time
    return b.hh < a.ehh || (b.hh == a.ehh && b.mm < a.emm);
}

int eventScheduler(Event* Array, int N){
    if(N==0)return 0;
    std::sort(Array,Array+N,[](Event a,Event b){
        return a.ehh < b.ehh || (a.ehh == b.ehh && a.emm < b.emm);
    });

    int result=1;
    Event lastChosen= Array[0];
    for(int i=1;i < N;i++){
        if(!overlapping(lastChosen,Array[i])){
            result++;
            lastChosen=Array[i];
        }
    }
    return result;
}

为什么这样起作用的直觉:如果我们选择数组的第一个事件,那么所有无法选择的事件都将包含第一个事件的完成时间,因此无法从该子集中选择多个事件。选择第一个事件可最大程度地减少完成时间,从而可以安排更多事件。丢弃这些事件后,我们将处于开始状态。