背包问题,递归方法的动态优化

整体思路:

        当没有物品时候返回0【递归终点】。

                当第i个物品体积超过背包容量时,在前i-1个物品中计算最大价值【递归终点】,

                 当第i个物品体积不超过背包容量时,偷的结果

                                                                           不偷的结果

 

用【递归】实现背包问题:

#coding=utf-8

class Kapsnack(object):

    def __init__(self):
        self.weight = [0, 2, 2, 6, 5, 4]
        self.values = [0, 6, 3, 5, 4, 6]


    def comput(self, n=5, w=10):
        
        if n < 0:
            return 0
        if self.weight[n] > w:
            return self.comput(n-1, w)
        else:
            result1 = self.comput(n-1, w-self.weight[n]) + self.values[n]
            result2 = self.comput(n-1, w)
            return max(result1, result2)

n = 5
w = 10
result = Kapsnack().comput(n, w)
print('背包容量是{}的情况下,能偷到的最大的价值是{}'.format(w,result))

#背包容量是10的情况下,最大的价值是15

后期要优化递归中重复计算问题。

Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

上面算法中无论第五件物品偷不偷,result1和result2都会计算一遍第四件物品的偷不偷问题,重复计算。

 

【字典优化版】的递归背包问题:

#coding=utf-8

import timeit


class Kapsnack(object):

    def __init__(self):
        self.weight = [0, 2, 2, 6, 5, 4]
        self.values = [0, 6, 3, 5, 4, 6]
        self.temp_dic = {}


    def comput(self, n, w):
        #若字典里没有计算值
        if self.temp_dic.get(n, "NoResult") == "NoResult":
            print("字典没有结果需要计算,n是%d"%n)
            #就计算
            if n < 0 or w <= 0:
                return 0
            if self.weight[n] > w:
                return self.comput(n-1, w)
            else:
                result1 = self.comput(n-1, w-self.weight[n]) + self.values[n]
                result2 = self.comput(n-1, w)
                max_result = max(result1, result2)
                #计算结果扔到字典里
                self.temp_dic[n] = max_result
            return max_result
        #字典有值直接返回
        else:
            print("有结果,n是%d"%n)
            return self.temp_dic[n]

n = 5
w = 10
result = Kapsnack().comput(n, w)
print('背包容量是{}的情况下,能偷到的最大的价值是{}'.format(w,result))
print(timeit.timeit("Kapsnack().comput(5, 10)", setup="from __main__ import Kapsnack", number=100))

"""
...
字典没有结果需要计算,n是5
字典没有结果需要计算,n是4
字典没有结果需要计算,n是3
字典没有结果需要计算,n是2
字典没有结果需要计算,n是1
字典没有结果需要计算,n是0
字典没有结果需要计算,n是-1
字典没有结果需要计算,n是-1
字典没有结果需要计算,n是3
字典没有结果需要计算,n是2
字典没有结果需要计算,n是1
有结果,n是0
字典没有结果需要计算,n是2
字典没有结果需要计算,n是1
有结果,n是0
有结果,n是0
有结果,n是1
有结果,n是4
背包容量是10的情况下,能偷到的最大的价值是15

0.01601231499807909

"""

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值