首页 > 技术文章 > 回溯法解最佳调度问题(python实现)

yppah 2019-12-08 16:47 原文

1、问题描述:设有n个任务由k个可并行工作的机器来完成,完成任务i需要时间为ti。试设计一个算法找出完成这个任务的最佳调度,使完成全部任务的时间最早。

2、算法设计:对任意给定的整数n和k,以及完成任务i需要的时间为ti(i=1~n)。计算完成这n个任务的最佳调度。

3、数据输入:由文件input.txt给出输入数据。第1行有2个正整数n和k。第2行的n个正整数是完成n个任务需要的时间。

4、结果输出:将计算的全部任务的最早时间输出到文件output.txt。

5、输入文件示例:             输出文件示例:

             input.txt                    output.txt

             7 3                              17

             2 14 4 16 6 5 3

6、实现思路:   

   用一棵深度为n的k叉树表示解空间。   

(1)搜索从开始结点(根结点)出发,以DFS搜索整个解空间。 

(2)每搜索完一条路径则记录下t和best序列,开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处向纵深方向移至一个新结点,并成为一个新的活结点,也成为当前扩展结点。

(3)如果在当前的扩展结点处不能再向纵深方向扩展,则当前扩展结点就成为死结点。此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点;直至找到一个解或全部解。

解空间如下图所示。例如:机器数为3,则为3叉树;任务数为4,则树深度为4;用3台机器去调度4个任务,把这棵树深度遍历后,最终选出最优值。

7、代码:

# 5-15最佳调度问题

n = 0  # 任务数
k = 0  # 机器数
best = 99999  # 最优值(完成全部任务的最早时间)
len = []  # 每台机器已安排的时间
t = []  # 每个任务所需的时间
x = []  # 当前路径(调度)
bestx = []  # 最优路径(调度)


# 计算任务完成的时间
def comp():

    tmp = 0
    for i in range(k):
        if len[i] > tmp:
            tmp = len[i]
    return tmp


# 以深度优先遍历方式遍历解空间树
def search(dep, len, t):

    global best

    if dep == n:
        tmp = comp()
        if tmp < best:
            best = tmp
            for i in range(n):
                bestx[i] = x[i]
        return

    for i in range(k):
        len[i] += t[dep]
        x[dep] = i + 1
        if len[i] < best:
            search(dep + 1, len, t)
        len[i] -= t[dep]


if __name__=="__main__":

    strN = input("请输入任务数n:")
    strK = input("请输入机器数k:")
    n = int(strN)
    k = int(strK)

    strT = input("请输入完成{}个任务需要的时间(以空格分隔,以回车结束):".format(n))
    t = strT.split(" ")
    t = list(map(int, t))  # str转为int

    len = [0 for _ in range(k)]  # k长度
    x = [0 for _ in range(n)]  # n长度
    bestx = [0 for _ in range(n)]  # n长度

    search(0, len, t)
    print("最优值:", best)
    print("最优解:", bestx)

8、测试:

(1)输入:n=7,k=3,t=[2, 14, 4, 16, 6, 5, 3]

          输出:best=17,bestx=[1, 2, 1, 3, 1, 1, 2]

(2)输入:n=9,k=4,t=[10, 14, 3, 9, 21, 6, 18, 16, 5]

          输出:best=26,bestx=[1, 2, 2, 2, 3, 4, 4, 1, 3]

 

推荐阅读