# -*- coding: utf-8 -*-
'''
Python程序员面试算法宝典---解题总结: 第4章 数组 4.25 如何对任务进行调度
题目:
假设有一个中央调度机,有n个相同的任务需要调度到m台服务器上去执行,由于
每台服务器的配置不一样,因此,服务器执行一个任务所花费的时间也不同。
现在假设第i个服务器执行一个任务所花费的时间也不同。
现在假设第i个服务器执行一个任务需要的时间为t[i]。
例如: 有2个执行机a与b。执行一个任务分别需要7min, 10min,
有6个任务待调度。如果平分这6个任务,即a与b各3个任务,
则最短需要30min执行完所有。
如果a分4个任务,b分2个任务,则最短28min执行完。
请设计调度算法,使得所有任务完成所需要的时间最短,
输入m台服务器,每台机器处理一个任务的时间为t[i],
完成n各任务,输出n个任务在m台服务器分布:
estimate_process_time(t, m, n)。
分析:
关键:
1 书上解法
贪心算法。用一个数组记录每台机器:
已经分配任务的执行时间+这个任务所需要的时间,选取
最短时间的机器进行处理。
2 贪心算法
贪心算法具有如下性质:
1)常用于求解最大最小值问题
2) 贪心算法的组成分为
贪心选择:
所求问题的全局最优解可以通过一系列局部最优解的选择来达到
(当前状态选取哪个可以达到局部最优解)
最优子结构:
问题最优解中包含它的子问题最优解
(假设最优解为Sn那么子问题的最优解是Sn-1,
并且Sn-1属于Sn, Sn-1并上第一个被选择的元素即为Sn)
3 我没想到
是因为忘记了贪心算法求最小/最大值,
包含贪心选择(全局最优解可以通过局部最优解选择来达到)
和最优子结构(问题最优解包含它的子问题最优解)
另外任务的选取需要选择当前服务器已经耗费的时间和这次分配任务时间之和
的最小值。
参考:
Python程序员面试算法宝典
https://blog.csdn.net/qingyuanluofeng/article/details/47776263
'''
'''
选取数组中最小的元素,并返回该最小元素对应的索引
'''
def minValue(array, timeArr=None):
if not array:
return
minNum = float('inf')
minIndex = 0
timeLen = len(timeArr) if timeArr else 0
for i, value in enumerate(array):
if not timeArr:
if value < minNum:
minNum = value
minIndex = i
else:
# 计算已经耗时的任务和当前该任务执行需要花费的时间中的最小值
if i < timeLen and value + timeArr[i] < minNum:
minNum = value + timeArr[i]
minIndex = i
return minNum, minIndex
def estimate_process_time(t, m, n):
if not t:
return
if m <= 0 or n <= 0:
return
# 记录m台机器每台机器已经执行的任务时间
cost = [0 for i in range(m)]
i = 0
while i < n:
minNum, minIndex = minValue(cost, t)
# 选取已经花费时间+当前任务所需要时间的和中耗时最短的
cost[minIndex] += t[minIndex]
i += 1
# 计算总的耗时时间,即计算cost数组中的最大值即为所求
totalTime = float('-inf')
# 计算每个服务器分配的任务序列
taskArr = [0 for i in range(m)]
for i, value in enumerate(cost):
if value > totalTime:
totalTime = value
if value > 0:
taskArr[i] = value / t[i] if t[i] != 0 else 0
return totalTime, taskArr
def process():
t = [7, 10]
n = 6
m = len(t)
totalTime, taskArr = estimate_process_time(t, m, n)
print "耗时最少为:"
print totalTime
print "任务分配序列为:"
print taskArr
if __name__ == "__main__":
process()