python实现分数背包和01背包【贪心,动态规划,暴力】(注释版)

目录

详细需求

详细代码

文件结构

fuction.py

Lab3.py


详细需求

要求在一个物品集合中选择合适的物品放入背包,在放入背包中的物品总重量不超过背包容量的前提下,希望放入背包的物品总价值最大。根据是否允许部分物品放入背包的要求,背包问题可以分为分数背包问题和0-1背包问题。

对于分数背包问题,可以通过设计贪心算法得到问题实例的最优解。对于0-1背包问题,该问题已经被证明为NP-Hard,即不存在多项式时间算法那求解,但可以通过贪心算法得到问题的近似解,或者通过蛮力法、动态规划法得到问题的最优解。

详细代码

文件结构

fuction.py

import numpy


def input_s():
    beibao_rongliang = int(input("输入背包容纳重量:"))
    shu_liang = int(input("输入商品数量:"))
    weights = []
    values = []
    for i in range(shu_liang):
        weight = int(input("输入第" + str(i + 1) + "个商品重量:"))
        value = int(input("输入第" + str(i + 1) + "个商品价值:"))
        weights.append(weight)
        values.append(value)
    return values, weights, beibao_rongliang


def greedy_for_fs(values, weights, beibao_rongliang):
    print("**************贪心算法分数****************")
    print("--------------性价比排序----------------")
    xing_jiabi = []
    for i in range(len(weights)):
        xing_jiabi.append(values[i] / weights[i])
    xing_jiabi = numpy.array(xing_jiabi)
    bigtoSmall = numpy.argsort(xing_jiabi)[::-1]
    values_new = []
    weights_new = []
    zong_jiazhi = 0
    for i in range(len(bigtoSmall)):
        print("价值:", values[bigtoSmall[i]], "重量:", weights[bigtoSmall[i]])
    for i in range(len(bigtoSmall)):
        if (beibao_rongliang - weights[bigtoSmall[i]] >= 0):
            values_new.append(values[bigtoSmall[i]])
            weights_new.append(weights[bigtoSmall[i]])
            zong_jiazhi += values[bigtoSmall[i]]
            beibao_rongliang -= weights[bigtoSmall[i]]
        else:
            values_new.append(values[bigtoSmall[i]])
            weights_new.append(beibao_rongliang)
            zong_jiazhi += beibao_rongliang / weights[bigtoSmall[i]] * values[bigtoSmall[i]]
            break
    print("--------------背包物品----------------")
    for i in range(len(values_new)):
        print("价值:", values_new[i], "重量:", weights_new[i])
    print("总价值:", zong_jiazhi)


def greedy_for_01(values, weights, beibao_rongliang):
    print("**************贪心算法01****************")
    print("--------------性价比排序----------------")
    xing_jiabi = []
    for i in range(len(weights)):
        xing_jiabi.append(values[i] / weights[i])
    xing_jiabi = numpy.array(xing_jiabi)
    bigtoSmall = numpy.argsort(xing_jiabi)[::-1]
    values_new = []
    weights_new = []
    zong_jiazhi = 0
    for i in range(len(bigtoSmall)):
        print("价值:", values[bigtoSmall[i]], "重量:", weights[bigtoSmall[i]])
    for i in range(len(bigtoSmall)):
        if (beibao_rongliang - weights[bigtoSmall[i]] >= 0):
            values_new.append(values[bigtoSmall[i]])
            weights_new.append(weights[bigtoSmall[i]])
            zong_jiazhi += values[bigtoSmall[i]]
            beibao_rongliang -= weights[bigtoSmall[i]]
        else:
            break
    print("--------------背包物品----------------")
    for i in range(len(values_new)):
        print("价值:", values_new[i], "重量:", weights_new[i])
    print("总价值:", zong_jiazhi)


def testout(values, weights, beibao_rongliang):
    print("--------------测试输出----------------")
    print("背包容纳重量:", beibao_rongliang)
    for i in range(len(weights)):
        print("价值:", values[i], "重量:", weights[i])


def erToten(num, length):
    num_list = []
    while (num / 2 != 0):
        num_list.insert(0, num % 2)
        num = num // 2
    if (len(num_list) < length):
        for i in range(length - len(num_list)):
            num_list.insert(0, 0)
    return num_list


def brute_for_01(values, weights, beibao_rongliang):
    print("**************暴力算法01****************")
    zong_jiazhi = 0
    condition = []
    for i in range(2 ** len(values)):
        condition.append(erToten(i, len(values)))
    for i in condition:
        linshi_jiazhi = 0
        zong_zhongliang = 0
        print(i, end="")
        for j in range(len(i)):
            if (i[j] == 1):
                zong_zhongliang += weights[j]
                linshi_jiazhi += values[j]
        print("临时价值:", linshi_jiazhi)
        if (linshi_jiazhi > zong_jiazhi and zong_zhongliang <= beibao_rongliang):
            zong_jiazhi = linshi_jiazhi
    print("最有价值:", zong_jiazhi)


def dynamic_for_01(values,weights,beibao_rongliang):
    print("**************动态规划01****************")
    value=[]
    for i in range(len(values)+1):
        value_linshi=[]
        for j in range(beibao_rongliang+1):
            value_linshi.append(0)
        value.append(value_linshi)
    # for i in value:
    #     print(i)
    for i in range(1,len(values)+1):
        for j in range(1,beibao_rongliang+1):
            #不放入
            value[i][j]=value[i-1][j]
            #放入
            #确保当前背包的剩余容量大于或等于第 i 个物品的重量 并且放入时,最优解是第 i 个物品的价值 values[i - 1]
            # 加上剩余容量 w - weights[i - 1] 时的最优解,即 values[i - 1] + dp[i - 1][w - weights[i - 1]]。
            if j >= weights[i - 1] and value[i][j] < value[i - 1][j - weights[i - 1]] + values[i - 1]:
                value[i][j] = value[i - 1][j - weights[i - 1]] + values[i - 1]
    for i in value:
        print(i)
    x = [False for i in range(beibao_rongliang)]
    for i in range(len(values), 0, -1):
        if value[i][j] > value[i - 1][j]:
            x[i - 1] = True
            j -= weights[i - 1]
    print('所装物品为:',end="")
    for i in range(len(values)):
        if x[i]:
            print('第', i + 1, '个,', end='')
    print("最大价值:",value[len(values)][beibao_rongliang])


def dynamic_for_01_youhua(values, weights, beibao_rongliang):
    print("**************动态规划优化01****************")
    #这里引入了一个名为 memo 的二维数组,用于存储已经计算过的子问题的结果。在 dp 函数中,
    # 首先检查 memo[i][w] 是否已经计算过,如果是,则直接返回该值,避免重复计算。如果没有计算过,
    # 则按照原有的递归逻辑计算,并将结果存入 memo[i][w] 中。
    n = len(weights)
    memo = [[-1 for i in range(beibao_rongliang + 1)] for i in range(n + 1)]

    def dp(i, w):
        if i == 0 or w == 0:
            return 0
        if memo[i][w] != -1:
            return memo[i][w]
        if weights[i - 1] > w:
            memo[i][w] = dp(i - 1, w)
        else:
            memo[i][w] = max(dp(i - 1, w), values[i - 1] + dp(i - 1, w - weights[i - 1]))

        return memo[i][w]

    print("最大价值:",dp(n, beibao_rongliang))

Lab3.py

import fuction as ft

# values, weights, beibao_rongliang = ft.input_s()
values=[1,7,5,8]
weights=[4,2,3,4]
beibao_rongliang=7
ft.testout(values,weights,beibao_rongliang)
ft.greedy_for_fs(values, weights, beibao_rongliang)
ft.greedy_for_01(values,weights,beibao_rongliang)
ft.brute_for_01(values,weights,beibao_rongliang)
ft.dynamic_for_01(values,weights,beibao_rongliang)
ft.dynamic_for_01_youhua(values,weights,beibao_rongliang)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值