北京工业大学研究生算法作业(二)——01背包问题

算法思路

利用动态规划算法,寻找每个状态下背包内物品的最优解,最终得出最终最优解。

Readme

运行说明:
7个.dat后缀文件保存了7组地址数据储存于data文件夹中,将.py和.exe文件放在data的父级文件夹中。直接运行01Packet.exe,将显示每组数据的原始数值,和背包价值最优解以及放入背包的物品序号。程序窗口将保持300秒。

数据结构:
整型product_count:物品数量
整型capacity:背包容量
列表weight_array:物品重量
列表value_array:物品价值

算法设计:
1、首先从配置文件中获取物品数量、背包容量、物品重量和物品价值,分别存入上述对应的数据结构中。
2、定义一个二维列表value,其行数为物品数量+1,其列数为背包容量+1,初始化二维列表中所有值为0。
3、value[i][j]代表当前背包剩余容量j的条件下,前i个物品的最优解。
4、在每一种容量条件下遍历每一件物品,将现有状态value与前一状态value对比,即当背包可以装下物品i,且装下比不装下的value值更大,则装入。
5、递归完成二维列表value的每一值设定,二维列表内最大值即为最优解(价值最大)。
6、从最优解处回溯,当二维列表第i行大于第i-1行同一位置的值时,则代表放入第i个物品,并减去对应重量。
7、回溯至value[0][0],可得出放入的所有物品。

代码

# -*- coding: utf-8 -*-
import time
import glob

# 定义01背包问题的类
class Packet:
    #初始化参数物品数量,背包容量,重量,价值
    def __init__(self,product_count,capacity,weight_array,value_array):
        self.product_count = product_count
        self.capacity = capacity
        self.weight_array = weight_array
        self.value_array = value_array

    # data函数用于打印每组数据
    def data(self):
        print('物品个数:', self.product_count)
        print('背包容量:', self.capacity)
        print('商品重量:', self.weight_array)
        print('商品价值:', self.value_array)

    # 动态规划算法
    def Dynamic_Planning(self):
        #value[i][j]:当前背包容量 j,前 i 个物品最佳组合对应的价值,初始化置0,
        value = [[0 for j in range(self.capacity + 1)] for i in range(self.product_count + 1)]
        # 利用循环使每一个物品遍历背包容量
        for i in range(1, self.product_count + 1):
            for j in range(1, self.capacity + 1):
                value[i][j] = value[i - 1][j] # 将背包置于放入上一个物品的状态(前一状态)
                # 当背包剩余容量大于等于当前物品,且前一状态价值(由于上一条语句,此时前一状态为value[i][j])小于现状态价值时,置换
                if j >= int(self.weight_array[i - 1]) and value[i][j] < value[i - 1][j - int(self.weight_array[i - 1])] + int(
                        self.value_array[i - 1]):
                    value[i][j] = value[i - 1][j - int(self.weight_array[i - 1])] + int(self.value_array[i - 1])
        return value

    # 打印最优解
    def show(self):
        # 从最优解处遍历物品,当value大于上一行同样位置的value时,表示放进该物品
        value = self.Dynamic_Planning()
        print('最大价值为:', value[self.product_count][self.capacity])
        x = [False for i in range(self.product_count)]
        j = self.capacity
        for i in range(self.product_count, 0, -1):
            if value[i][j] > value[i - 1][j]:   #此行大于上一行同位置的值
                x[i - 1] = True          # 放入该物品
                j -= int(self.weight_array[i - 1])       # 减少对应背包容量
        print('背包中所装物品为:')
        for i in range(self.product_count):
            if x[i]:
                print('第' + str(i + 1) + '个 ', end=' ')

def main():
    file = glob.glob('./data/*.dat')   # 获取指定目录下所用.dat后缀文件
    for i,filename in enumerate(file): # 循环获取序号与文件名
        # filename = "input_assign01_0"+str(i+1)+".dat"
        print('\n\n第%d组数据'%(i+1))

        # 打开文件,逐行读取数据
        with open(filename, 'r') as f:
            product_count = f.readline()
            capacity = f.readline()
            weight_array = f.readline()
            value_array = f.readline()

            # 将重量与价值转化为列表形式
            weight_array = weight_array.strip().split(" ")
            value_array = value_array.strip().split(" ")
            product_count = int(product_count)
            capacity = int(capacity)

        Packet(product_count, capacity, weight_array, value_array).data()  # 调用类方法data
        Packet(product_count, capacity, weight_array, value_array).show()  # 调用类方法show
    print('\nFinish!')
    time.sleep(300)

if __name__ == '__main__':
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值