动态规划:小偷的背包

《算法图解》第九章,小偷的背包问题,顺便记录一下:

import copy

def fillbag(bagsize, goods):
    bagsvalue = [[{}]*bagsize for x in range(len(goods))]
    
    def bestbag( m, n, leftweight, value, name):
        ‘‘‘
        m, 行号,同时表示 m 种物品
        n, 列, 同时表示当前背包大小    
        leftweight, 剩余空间,
        value, 当前物品价值
        name, 当前物品
        ‘‘‘
        # 注意:
        # 使用 m_sub1, 说明问题域为 m-1 种物品(排除当前物品,说明每种物品只有一个,不可重复)
        # 背包大小为 leftweight 
        m_sub1 = m-1
        a = bagsvalue[m_sub1][n]["v"]
        b = value
        if leftweight != 0:
            b += bagsvalue[m_sub1][leftweight-1]["v"]
        if a > b:
            return copy.deepcopy(bagsvalue[m_sub1][n])
        else:
            if leftweight == 0:
                return {"v":v,"gs":[name]}
            else:
                bag = copy.deepcopy(bagsvalue[m_sub1][leftweight-1])
                bag["v"]=b
                bag["gs"].append(name)
                return bag

    for i in range(len(goods)):
        na = goods[i]["name"]
        w = goods[i]["weight"]
        v = goods[i]["value"]
        for j  in range(bagsize):
            # 背包当前大小
            cw = j+1
            if i == 0:
                if w <= (j+1):
                    bagsvalue[i][j] = {"v":v,"gs":[na]}
                else:
                    bagsvalue[i][j] = {"v":0,"gs":[]}
                continue
            # 剩余空间
            lw = cw - w
            if cw < w:
                bagsvalue[i][j] = copy.deepcopy(bagsvalue[i-1][j]) 
            else:
                bagsvalue[i][j] = bestbag(i,j,lw,v,na)
    return bagsvalue


def main():
    bagsize = 4;
    goods = [{"name":"soundbox","weight":4,"value":3000},
        {"name":"guitar","weight":1,"value":1500},  
        {"name":"laptop","weight":2,"value":2000},
        {"name":"iphone","weight":1,"value":2000}]
    bagvalues =  fillbag(4,goods)
    print(bagvalues)

if __name__ == "__main__":
    main()

如果是同一种物品数量不限,肯定是按照单位价值的高低朝包里收拾啦。