背包问题解决方案 贪婪策略--近优解 而不是最优解

2019最后一天 各位小伙伴加油啊 本周作业(12.30-1.12)
本周作业内容如下:假设小偷有一个背包,最多能装20公斤赃物,
#他闯入一户人家,发现如下表所示的物品。很显然,他不能把所有物品都装进背包,所以必须确定拿走哪些物品,
留下哪些物品。
#名称价格(美元)重量(kg)
#电脑 200 20
#收音机 20 4
钟 175 10
#花瓶 50 2
书 10 1
#油画 90 9

#这次作业 是阿里巴巴与四十大盗—背包问题一样。
#是用一种贪婪策略去实现的
#一个贪心算法总是做出当前最好的选择,也就是说,它期望通过局部最优选择从而得到全局最优的解决方案

此题尝试用贪心策略 包含如下
每次挑选价值最大的
2每次挑选重量最小的
3每次挑单位重量价值最大的宝物 也就是性价比
比较三个策略 第三种方法应该比较好

import numpy as np
原有的字典: 美元 重量
old_dic = {'电脑': [200, 20], '收音机': [20, 4], '钟': [ 175, 10], '花瓶': [50, 2], '书': [10, 1], '油画': [90, 9]}
 根据性价比获得的新字典 : 美元 重量 性价比
new_dic = {'电脑': [200, 20, 10], '收音机': [20, 4, 5], '钟': [ 175, 10, 17.5], '花瓶': [50, 2, 25], '书': [10, 1, 10], '油画': [90, 9, 10]}

temp_old_dic = [[200, 20], [20, 4], [175, 10], [50, 2], [10, 1], [90, 9]]
背包问题解决方案类
class BagSolution:

    '''
    这次作业 是阿里巴巴与四十大盗---背包问题一样。
    是用一种贪婪策略去实现的# 一个贪心算法总是做出当前最好的选择,也就是说,它期望通过局部最优选择从而得到全局最优的解决方案
    此题尝试用贪心策略 包含如下
    1每次挑选价值最大的
    2每次挑选重量最小的
    3每次挑单位重量价值最大的宝物  也就是性价比
    比较三个策略 第三种方法应该比较好

    '''

    def __init__(self, dic: dict,bagWeight):
       self.dic = dic
       self.bagWeight = bagWeight

    # 每次挑选价值最大的
    def valueMax(self,index):

        #字典排序 
        if index == 1:
            tempidct = sorted(new_dic.items(),key = lambda item:item[1][0],reverse = True)      
        elif index == 2:
            tempidct = sorted(new_dic.items(),key = lambda item:item[1][1])  
        elif index == 3:
            tempidct = sorted(new_dic.items(),key = lambda item:item[1][2],reverse = True)
            # print(tempidct)
        print('*' * 50)
        tempWeight = 0
        tempValue = 0
        for i in range(len(tempidct)):

            tempWeight += tempidct[i][1][1] 
           
            if self.bagWeight - tempWeight >= 0 :
                tempValue += tempidct[i][1][0]
            else:
                tempWeight -= tempidct[i][1][1] 
                continue

            print('拿了{}价值{}重量{} '.format(tempidct[i][0],tempidct[i][1][0],tempidct[i][1][1]))
       
 
        print('一共背了{}kg'.format(tempWeight))
        print('一共背了价值{}美元的货物'.format(tempValue))

    '''
    动态规划的方式 把0-1背包问题解决的
    动态规划就是把原问题分解为若干子问题,先解决最小的问题,把结果存到表中
    再求解大问题

    '''
    def valueMax1(self):
        # i 表示几件物品
        # j 表示背包重量
        tempBagWeight = 0
        matrix = np.zeros((len(old_dic),self.bagWeight),dtype=np.int32)                                                               # 列出所有的可能 
        # print(matrix)
        for i in range(len(old_dic)):                                                                                                 #列出从1件物品到最大物品
            for j in range(self.bagWeight+1):
                if j > temp_old_dic[i][1]:                               
                    matrix[i][j-1] = max(matrix[i-1][j-1],matrix[i-1][j-1-temp_old_dic[i][1]] + temp_old_dic[i][0])                   #每件物品装到背包最佳值
                elif j == temp_old_dic[i][1]:
                    matrix[i][j-1] =  temp_old_dic[i][0]                                                                              # 如果装不下, 那就相当于没有这个物品
                else:
                    matrix[i][j-1] =  0
            # print('拿了{}价值{}重量{} '.format(old_dic[i][0],old_dic[i][1][0],old_dic[i][1][1]))

        print(matrix)      
        print(matrix[-1][-1])





b = BagSolution(new_dic,20)
b.valueMax(1)       #方案1
b.valueMax(2)       #方案2
b.valueMax(3)       #方案3

b.valueMax1()

#打印之后 发现20kg的背包 第三个方案拿的价值最高

故 一共背了17kg一共背了价值255美元的货物 是近似最优解


拿了电脑价值200重量20
一共背了20kg
一共背了价值200美元的货物


拿了书价值10重量1
拿了花瓶价值50重量2
拿了收音机价值20重量4
拿了油画价值90重量9
一共背了16kg
一共背了价值170美元的货物


拿了花瓶价值50重量2
拿了钟价值175重量10
拿了书价值10重量1
拿了收音机价值20重量4
一共背了17kg
一共背了价值255美元的货物

价值275美元的货物 最优解

[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 200]
[ 0 0 0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 200]
[ 0 0 0 0 0 0 0 0 0 175 175 175 175 195 195 195 195 195
195 200]
[ 0 50 50 50 50 50 50 50 50 175 175 225 225 225 225 245 245 245
245 245]
[ 10 50 60 60 60 60 60 60 60 175 185 225 235 235 235 245 255 255
255 255]
[ 0 0 0 0 0 0 0 0 90 175 185 225 235 235 235 245 255 255
265 275]]
275

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值