算法作业
有n项工作,工作j的开始时间是sj,结束时间是fj,完成工作j获得的报酬是wj; 如果两项工作的时间没有重叠,则同一个人可以完成两项工作;目标:在同一个人可以完成的工作中,找出所获报酬最大的工作集合; 输入: 第一行输入工作的数量 第二行开始,每行输入一个工作编号和对应的报酬、开始时间以及结束时间,以空格隔开,时间按XX:YY:ZZ的格式 输出: 第一行输出所获报酬最大的工作编号集合 第二行输出对应的最大报酬 例子: 输入: 3 3 6 09:10:00 10:10:00 1 10 08:00:00 09:00:00 2 8 08:30:00 9:30:00 输出: {1,3} 16 1 5 08:00:00 9:57:02 2 6 09:00:00 11:00:00 3 7 10:00:00 11:50:00 4 8 11:30:00 13:10:00 5 9 12:00:00 14:00:00
from collections import defaultdict
# 按结束时间排序
def Sort(W):
n = len(W)
for i in range(n):
for j in range(n - i - 1):
if W[j][3] > W[j + 1][3]:
W[j], W[j + 1] = W[j + 1], W[j]
return
# 找出前一个和它不冲突的
def PRE(W):
n = len(W)
PRE = defaultdict(list)
for i in range(n - 1, -1, -1):
PRE[W[i][0]] = '0'
for j in range(i - 1, -1, -1):
if W[j][3] <= W[i][2]:
PRE[W[i][0]] = W[j][0]
break
return PRE
# 带权区间调度
def ALG(W, PRE):
# 每个点走过的路径
L = defaultdict(list)
L[W[0][0]].append(W[0][0])
# 报酬最大路径
most = []
# 每个点的最大报酬
T = defaultdict(int)
n = len(W)
for i in range(n):
if i > 1:
L[W[i][0]] = L[PRE[W[i][0]]].copy()
L[W[i][0]].append(W[i][0])
T[W[i][0]] = W[i][1]
# 如果当前报酬(本身报酬+不冲突的前一个点的报酬) > 前一个点的报酬,则更新本点报酬
if T[W[i][0]] + T[PRE[W[i][0]]] > T[W[i - 1][0]]:
T[W[i][0]] += T[PRE[W[i][0]]]
most = L[W[i][0]]
else:
T[W[i][0]] = T[W[i - 1][0]]
print("工作编号:", most)
print("最大报酬:", T[W[n - 1][0]])
return
if __name__ == '__main__':
# 输入
n = int(input("请输入工作数量:"))
W = []
print("请依次输入:工作编号、报酬、起始时间、结束时间:")
for i in range(n):
job, wage, start_time, end_time = input().split(" ")
s_h, s_m, s_s = map(int, start_time.split(":"))
e_h, e_m, e_s = map(int, end_time.split(":"))
start = s_h * 3600 + s_m * 60 + s_s
end = e_h * 3600 + e_m * 60 + e_s
W.append((job, int(wage), start, end))
# 按结束时间排序
Sort(W)
print("按结束时间排序后:", W)
print("每个工作上一个不冲突", (PRE(W)))
ALG(W, PRE(W))