背包问题简述

背包问题算法和原理

         现有一个容量为Vol的背包,N个种类的物品,第i个物品的容量为weight[i],现在汪背包里面装东西,

怎么才能使背包物品的总价值才是最大的?主要分为三类:0-1背包,完全背包和多重背包问题

1,0-1背包问题

      每件物品都可能被带走或者是留下,只能取0或1

                                     

def zero_one_Pack(Num,Vol,weight,value):
    '''
    0-1 背包问题(即每个物品只取一次或者不取)
    :Param N 物品的个数 如 N=5
    :Param V 背包的总容量,如 V=15
    :Param weight 每个物品的重量数组    weight = [5,4,7,2,6]
    :Param value 每个物品的机制数组表示,values = [12,3,10,3,6]
    :return 返回最大的总价值 
    '''
    # 初始化f[N+1][V+1]为0,f[i][j]对应前i个物品放入背包容量为j的最大价值
    f = [[0 for col in range(Vol+1)] for row in range(Num+1)]
    for i in range(1,Num+1):
        for j in range(1,Vol+1):
            if j < weight[i-1]:     # 当容量小于商品i的重量时,直接不放入
                f[i][j] = f[i-1][j]
            else:
                # weight,Value下标是从0开始,第i个商品的重量为Weight[i-1],价值为Value[i-1] 
                f[i][j] = max(f[i-1][j],f[i-1][j-weight[i-1]]+value[i-1]) # 状态方程
    max_value=f[Num][Vol]
    for _ in f:
        print(_)
    return max_value

if __name__ == "__main__":
    N,V =5,15
    weight = [5,4,7,2,6]
    values = [12,3,10,3,6]
    sol = zero_one_Pack(N,V,weight,values)
    print(sol)

2,完全背包问题(部分背包问题)

     物品可能被带走可以是无限次取,例如偷金沙

                                    

def complete_Pack(Num,Vol,weight,value):
    ''' 
       完全背包问题(每个物品可以无限次取)
       Param: Num 物品的个数 如 N=5
       Param: Vol 背包的总容量,如 V=15
       Param: weight 每个物品的重量数组  
       Param: value 每个物品的机制数组表示
       return: 返回最大的总价值 
    '''
   # 初始化f[Num+1][Vol+1],为0
    f = [[0  for col in range(Vol+1)] for row in range(Num+1)]

    for i in range(Num+1):
        for j in range(Vol+1):
            f[i][j] = f[i-1][j]
            for k in range(j//weight[i-1]+1):
                if f[i][j] < f[i][j-k*weight[i-1]]+k*value[i-1]:
                    f[i][j] = f[i][j-k*weight[i-1]]+k*value[i-1]
    max_value =f[Num][Vol]
    for _ in f:
        print(_)
    return max_value

if __name__ == "__main__":
    N,V =5,15
    weight = [5,4,7,2,6]
    values = [12,3,10,3,6]
    sol = complete_Pack(N,V,weight,values)
    print('结果为:',sol)

3,多重背包问题

     物品被带走都是有限次,如第i个物品最多只能去num[i]次

                                      

def multi_Pack(Num,Vol,weight,value,num):
    """
        多重背包问题(每个物品都有次数限制)
        :Param Num 物品的个数 如 N=5
        :Param Vol 背包的总容量,如 V=15
        :Param weight 每个物品的重量数组 
        :Param value 每个物品的机制数组表示
        :return 返回最大的总价值 
        :param num_out: 每个物品的个数限制,如num=[2,4,1,5,3]
    """
    f = [[0 for col in range(Vol + 1)] for row in range(Num + 1)]
    for i in range(Num+1):
        for j in range(Vol+1):
            min_num = min(j//weight[i-1],num[i-1])
            f[i][j] = f[i-1][j]
            for k in range(min_num+1):
                if f[i][j] < f[i-1][j-k*weight[i-1]]+k*value[i-1]:
                    f[i][j] = f[i-1][j-k*weight[i-1]]+k*value[i-1]
    for _ in f:
        print(_)
    max_value = f[Num][Vol]
    return max_value

if __name__ == "__main__":
    N,V =5,15
    weight = [5,4,7,2,6]
    values = [12,3,10,3,6]
    num=[2,4,1,5,3]
    sol = multi_Pack(N,V,weight,values,num)
    print('结果为:',sol)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值