OD C卷 - 项目排期/最少交付时间
项目排期/最少交付时间(200)
- m个独立的需求,由n个开发者完成;
- 每个任务都是独立的,只能由一个人完成;
- 计算项目最少的交付时间;
输入描述:
第一行输入m个需求的工作量(天数),m在(0,30)之间,每个需求的天数<200
第二行输入人员数量n
输出描述:
项目最少的交付时间
示例1
输入:
6 2 7 7 9 3 2 1 3 11 4
2
输出:
28
示例2
输入:
2 3 4 2 5
3
输出:
6
示例3
输入:
100 50 30 10
3
输出:
100
思路:
- 二分求解
- 需求的工作量升序排序;
- 取完成需求的最小天数,计为 left = sum // n ;
- 取一个人完成时耗费的天数为最大,计为 right = sum;
- 二分法取 mid = (left + right) // 2,判断在这个mid以内是否能够在n个人之间完成需求的分配(每个人完成需求的天数<=mid);
- 若可以完成分配,则进一步减少天数,令result = mid; right = mid-1; 否则 left=mid+1;
- 需求的分配是从需求天数最小开始,依次分配给n个人,若给一个人分配后,其完成天数超出mid阈值,则将当前需求分配给下一个人
- 最后求得result
result = -1
class MinimumTime:
def solution(self, req_days, n):
# 总天数
total = sum(req_days)
self.m = len(req_days)
self.req_days = req_days
# 分配需求的数组
self.jobs = [0 for i in range(n)]
# 需求工作量 排序
req_days.sort()
# 最小天数
left = total // n
# 最大天数
right = total
# 依次求解
global result
while left <= right:
print("left:", left)
print("right:", right)
mid = (left + right) // 2
print("mid:", mid)
# 清空jobs
for i in range(n):
self.jobs[i] = 0
# 是否可以成功分配
if self.align_req(0, mid):
print("成功:")
result = mid
right = mid - 1
else:
print("失败:")
left = mid + 1
# low与最大的需求天数对比
# print(low if low > req_days[-1] else req_days[-1])
def align_req(self, days_idx, threshold):
# 递归分配任务
global n
if days_idx >= self.m:
# 分配完成
return True
i = 0 # 依次分配给n个人
while True:
if i >= n:
break
else:
total_v = self.req_days[days_idx] + self.jobs[i]
if total_v > threshold:
if self.jobs[i] == 0: # 还没分配 就超出阈值
break
else:
# 需求到开发 成功分配
self.jobs[i] += self.req_days[days_idx]
# 按照当前阈值,继续分配下一个需求
if self.align_req(days_idx + 1, threshold):
return True
# 下一个需求无法完成分配,当前分配撤销
self.jobs[i] -= self.req_days[days_idx]
i += 1
return False
if __name__ == '__main__':
mini_time = MinimumTime()
req_days = list(map(int, input("days:").strip().split()))
n = int(input("n:").strip())
mini_time.solution(req_days, n)
print(result)