回溯法:《装载问题》-python实现

有一批共n个集装箱要装上2艘载重量分别为c1和c2的船,其中集装箱i的重量为wi,且。装载问题要求确定是否有一个合理的装载方案可将这些集装箱装上这2艘船。如果有,找出一种装载方案。例如当n=3,c1=c2=50且w=[10,40,40]时,则可以将集装箱1和2装到第一艘轮船上,而将集装箱3装到第二艘轮船上;如果w=[20,40,40],则无法将这3个集装箱都装上轮船。容易证明,如果一个给定装载问题有解,则首先将第一艘船尽可能装满再将剩余的集装箱装上第二艘船可得到最优装载方案。将第一艘船尽可能装满等价于选取全体集装箱的一个子集,使该子集中集装箱重量之和最接近c1。

#coding:utf-8
import sys
import copy
c = 0

def judge(w2, a, i, j):
    if i + w2[j] <= a and w2[j] != 0:
        return True
    return False


def fenpei(w1, a, b, i, s1, jj):
    w2 = copy.deepcopy(w1)
    if i <= a and s1 - i <= b:                                  #当放入第一艘船的重量小于他的承重量,并且剩下的集装箱的重量和小于另一艘船的承载量,则满足条件
        global c
        c = c + 1
        print c
        print w2
    else:
        for j in range(jj, len(w2)):                            #从jj开始,防止出现重复的情况
            if judge(w2, a, i, j):                              #判断第j个集装箱是否可以放入第一艘船中
                t = w2[j]
                w2[j] = 0                                       #如果可以放入第一艘船中,将其置为0,表示已经放入第一艘船中
                fenpei(w2, a, b, i + t, s1, j)
                w2[j] = t                                       #再将该集装箱的重量恢复到原来,以便下一次回溯


if __name__ == '__main__':
    n = input()                                          #n表示一共有多少集装箱
    d = sys.stdin.readline().strip().split(' ')          #输入两个数,表示两艘船的承载量,以空格分割
    c1 = int(d[0])
    c2 = int(d[1])
    d1 = sys.stdin.readline().strip().split(' ')         #输入n个集装箱的重量,以空格分割
    w = map(int, d1)
    s = sum(w)                                           #表示所有集装箱的重量和

    fenpei(w, c1, c2, 0, s, 0)                           #w表示集装箱重量的列表,c1和c2分别表示两艘船的承载量,0表示放入第一艘船的重量,第二个0表示列表中的第几个集装箱,防止后边结果重复

    if c == 0:
        print 'no answer'

猜你喜欢

转载自blog.csdn.net/w113691/article/details/81558602