1. 程式人生 > 實用技巧 >python遞迴-揹包

python遞迴-揹包

遞迴程式碼Ⅰ:

w = [0, 2, 3, 4, 5, 9]
v = [0, 3, 4, 8, 8, 10]
max_W = 20
sum = {(i, w1):0 for i in range(len(w))
                    for w1 in range(max_W+1)}   
                    # python對資料操作的實現很容易


def m(i, W):  # 第i個物品怎麼放
    if i == 0:
        sum[(i, W)] = 0
        return 0
    elif W == 0:
        sum[(i, W)] = 0
        return 0
    elif sum[(i, W)] != 0:
        return sum[(i, W)]
    elif w[i] > W:
        sum[(i, W)] = m(i-1, W)
        return sum[(i, W)]
    else:
        sum[(i, W)] = max(m(i-1, W), v[i] + m(i-1, W-w[i]))
        return sum[(i, W)]

       

for i in range(1, len(w)):  # 填滿記憶陣列
    for j in range(1, max_W+1):
        m(i, j)
for i in range(1, len(w)):
    for j in range(1, max_W+1):
        print(i, '-', j, ':', sum[(i, j)])
print(sum[(len(w)-1, max_W)])  # 注意索引

遞迴程式碼Ⅱ:

tr = {(2, 3), (3, 4), (4, 8), (5, 8), (9, 10)}
val = {}

def thief(tr, m):
    if tr == set() or m == 0:
        val[(tuple(tr), m)] = 0  
        return 0
    
    elif (tuple(tr), m) in val:  # 記憶
        return val[(tuple(tr), m)]

    else:
        vmax = 0
        for t in tr:  # 取出一個合適的寶物再求處剩下寶物的最大值    
            if t[0] <= m:
                vmax = max(vmax, t[1] + thief(tr-{t}, m-t[0]))
        val[(t, m)] = vmax
        return vmax
        
# 秀
print(thief(tr, 20))

迭代

# 從小到大討論
tr = [None, {'w':2, 'v':3}, {'w':3, 'v':4},
            {'w':4, 'v':8}, {'w':5, 'v':8},
            {'w':9, 'v':10}]
max_m = 20
val = {(i, w):0 for i in range(len(tr))
                    for w in range(max_m+1)}

for i in range(1, len(tr)):  # 從小到大遞推,由於tr的第一項是None,因此得從第一項開始,range[1, len(tr)]
    for w in range(1, max_m+1):
        if tr[i]['w'] > w:  # 注意:這裡不是max_m
            val[(i, w)] = val[(i-1), w]
        else:
            val[(i, w)] = max(val[(i-1), w], tr[i]['v'] + val[(i-1), w-tr[i]['w']]) 

print(val[(len(tr)-1, max_m)])