他们给了我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;
}
}
答案 0 :(得分:0)
天真的解决方案可能是O(2 N ),但是:
当子集具有内部调度冲突时,您似乎有修剪逻辑,这已经极大地帮助了复杂性。
使用动态编程可以做得更好。这个问题听起来似乎具有很好的控制特征-如果一组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;
}
为什么这样起作用的直觉:如果我们选择数组的第一个事件,那么所有无法选择的事件都将包含第一个事件的完成时间,因此无法从该子集中选择多个事件。选择第一个事件可最大程度地减少完成时间,从而可以安排更多事件。丢弃这些事件后,我们将处于开始状态。