我创建了一个递归调度算法,该算法采用一个Event对象数组,这些对象包含一个开始时间和一个结束时间。这些时间是随机生成的,开始时间始终小于结束时间。时间是0-24之间的数字(一天24小时,24 == 0)
这是随机事件数组生成器的代码:
def randomEventArray(s):
e = []
rand1 = 0
rand2 = 0
for i in range(s):
rand1 = random.randint(0,21)
rand2 = random.randint(rand1+1,23)
e.append(Event(rand1,rand2))
return e
这是事件对象的代码:
class Event:
def __init__(self, start, end):
self.startTime = start
self.endTime = end
def __repr__(self):
return str(self)
def __str__(self):
return (str([self.startTime,self.endTime]))
现在是引起问题的部分。我创建了一段代码,该代码递归地处理了生成的事件数组,并列出了可以在24小时内举行的最多事件。任何事件都不应重叠。
这是创建的递归贪婪算法:
def scheduleGD2(E):
events = []
scheduleRecGD2(E,0,0, events)
return events[:]
def scheduleRecGD2(E, eventPos, startTime,events):
while eventPos < len(E) and E[eventPos].startTime < startTime:
eventPos += 1
if eventPos == len(E):
return []
minEndPos = eventPos
for i in range(eventPos+1, len(E)):
if E[i].endTime < E[minEndPos].endTime:
minEndPos = i
events.append(E[minEndPos])
return scheduleRecGD2(E, minEndPos+1, E[minEndPos].endTime, events)
E = randomEventArray(20)
print(scheduleGD2(E))
此算法的预期输出是具有最多事件的数组,这些事件可以在单个24小时内同时发生而不会发生重叠。例如
[[0, 1], [1, 3], [4, 8], [9, 17], [17, 24]]
但是,我收到以下输出:
[[0, 1], [12, 16], [12, 16], [5, 17], [21, 22]]
这清楚地表明Arr [2]与Arr [1](Arr [2] .StartTime(12) 出什么问题了,为什么会这样?
答案 0 :(得分:1)
我检测了您的代码以进行调试,包括用简单的对元组替换“事件”包。
def scheduleRecGD2(E, eventPos, startTime, events):
print("ENTER Rec", "eventPos", eventPos, "\tstartTime", startTime, "\n\tevents", events)
while eventPos < len(E) and E[eventPos][0] < startTime:
eventPos += 1
if eventPos == len(E):
return []
minEndPos = eventPos
print("\tFIRST: minEndPos", minEndPos, E[minEndPos])
for i in range(eventPos+1, len(E)):
if E[i][1] < E[minEndPos][1]:
minEndPos = i
events.append(E[minEndPos])
print("\tTRACE: minEndPos", minEndPos, E[minEndPos])
return scheduleRecGD2(E, minEndPos+1, E[minEndPos][1], events)
# Main program
E = randomEventArray(8)
print(E)
print(scheduleGD2(E))
输出:
[(15, 20), (4, 7), (17, 20), (18, 23), (2, 7), (8, 23), (15, 23), (18, 20)]
ENTER Rec eventPos 0 startTime 0
events []
FIRST: minEndPos 0 (15, 20)
TRACE: minEndPos 1 (4, 7)
ENTER Rec eventPos 2 startTime 7
events [(4, 7)]
FIRST: minEndPos 2 (17, 20)
TRACE: minEndPos 4 (2, 7)
ENTER Rec eventPos 5 startTime 7
events [(4, 7), (2, 7)]
FIRST: minEndPos 5 (8, 23)
TRACE: minEndPos 7 (18, 20)
ENTER Rec eventPos 8 startTime 20
events [(4, 7), (2, 7), (18, 20)]
[(4, 7), (2, 7), (18, 20)]
分析
您的算法多次跳闸。最重要的是,当您第二次进入该例程时,您会找到具有可接受的开始时间的第一条记录,并将其结束时间作为“击败数字”。从那时起,您将完全忽略呼叫中给定的开始时间以及其余事件的开始时间,而仅 寻找比相对任意间隔的结束时间还要好的时间。
您将以这种方式继续浏览列表,随意更改给定的开始时间,直到到达列表的结尾。
修复
遵循在线提供的许多解决方案:首先,按照结束时间的顺序对列表进行排序,然后按照开始时间进行排序。现在,遍历您的列表很简单,找到第一个可用的开始时间,该时间(a)在列表中的时间比最近添加的元组晚; (b)不小于当前结束时间。
鉴于解决方案的可用性,我将其留给学生作为练习。从对随机化例程的简单更改开始:
return sorted(e)