动态规划问题

动态规划问题严格分四步去考虑:问题结构分析——>递推关系建立——>自底向上计算(要知道最下层即最小单位)——>最优方案追踪

1.背包问题:

蛮力枚举:递归方法。

value=[24,2,9,10,9]
volume=[10,3,4,5,4]
def knapsack(value,volume,i,c):
    #从第i号商品到第4号商品,容量为c时候的最优解
    if c<0:
        return -10000#-10000是指返回了负无穷,让这个c小于0的时候一定不能被用上
    if i>4:
        return 0
    x=knapsack(value,volume,i+1,c)
    y=knapsack(value,volume,i+1,c-volume[i])+value[i]
    return max(x,y)
a=knapsack(value,volume,0,13)
print('使用暴力求解法,当背包的最大容量为13的时候,最优解为%d'%a)
# 使用暴力求解法,当背包的最大容量为13的时候,最优解为28

2.求最大子数组问题

solution1:蛮力枚举、

解法思路:

 

#最大紫书组问题。蛮力枚举
x=[-1,-3,3,5,-4,3,2,-2,3,6]
def voilence(x):
    shuzumax=-100000
    lens=len(x)
    for begin in range(0,lens):
        for end in range(begin,lens):
            s=0
            for i in range(begin,end+1):
                s+=x[i]
            if s>shuzumax:
                shuzumax=s

    return shuzumax
a=voilence(x)
print('最大值是%d'%a)
# 最大值是16

这个解法存在的最大问题就是重复!比如起点是下标为2、终点是下标为7和起点是下标为2、终点是下标为8的计算重复率很大。在计算从2 到8的时候,是不是直接可以借用从2到7的结果呢,最后只需要在从2 到7 的结果上加上一个数字即可;根据这个思路,我们提出了优化枚举法

solution 2:优化枚举法:

x=[-1,-3,3,5,-4,3,2,-2,3,6]
def voilence(x):
    shuzumax=-100000
    lens=len(x)
    for begin in range(0,lens):
        s = [0 for _ in range(lens-1 - begin + 1)]
        for ending in range(begin,lens):
            i=ending-begin
            if i==0:
                    s[0]=x[begin]
                    i+=1
            else:
                    s[i]=s[i-1]+x[ending]
        if max(s)>shuzumax:
            shuzumax=max(s)
    return shuzumax
for i in range(1000):
    a=voilence(x)
print('最大值是%d'%a)
#最大值是16

 通过time模块,可知优化之后所用时间减少了37.5%

import time
start = time.time()
'''
<代码块>
'''
end = time.time()
print("Running time: %s seconds"%(end - start))

solution3:分而治之策略

分而治之策略是指,将复杂问题分解成若干子问题分别求得最优解、最后获得最终的理想解。“分而治之”起名的来由是周王朝无法管辖所有的国土,便将土地分封给个个诸侯来管理,各个诸侯分给自己的士大夫、一级一级往下,最后以十户为一个治理单位,从而完成对于国家的治理,所以叫做分而治之法。

solution 4:动态规划

 

 在算D[i]之前,只需要保证D[i+1]和X[i]的值已知

 但由于单单凭借D[]数组和X[]数组我们无法记录数组最后的结果,所以引入record数组。来记录最后的结果。

record数组用于记录最优解的方案

将待求解数组依次往前走,若D[i+1]>0则rec[i]=rec[i+1]且D[i]=D[i+1]+X[i];若D[i+1]<0则rec[i]=i且D[i]=x[i] 

 完整代码如下:

def DP(shuzu):
    lens=len(shuzu)
    D=[0 for _  in range(0,lens)]
    # 注意一下D表示的是什么,D[i]表示的是从下标i开始的最大子序列
    rec=[0 for _  in range(0,lens)]
    # 注意一下rec是记录最优解是从哪里到哪里的,
    D[lens-1] = shuzu[lens-1]
    rec[lens-1] = lens-1
    for i in range(lens-2,-1,-1):
        if D[i+1]>0:
            D[i]=shuzu[i]+D[i+1]
            rec[i]=rec[i+1]
        else:
            D[i]=shuzu[i]
            rec[i]=i
    summax=max(D)
    summaxindex=D.index(max(D))
    return '最大子序列之和为%d,下标是从%d开始到%d'%(summax,summaxindex,rec[summaxindex])
#验证如下
print(DP([1,2,3,4,5]))
#最大子序列之和为15,下标是从0开始到4
print(DP([1,2,3,4,-9]))
最大子序列之和为10,下标是从0开始到3

3.最长公共子序列问题

先注意一下子序列的定义:子序列是指,将给定序列中零个或者多个序列中去掉之后的结果

注意公共子序列一定是不唯一的。

solution 1:蛮力枚举

 

 

 

 

 

 计算顺序确定如下:

 依然是建立一个rec数组进行跟踪

 

 

 

 

 

 

 

4.钢条切割问题

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值