zoukankan      html  css  js  c++  java
  • 动态规划DP算法

    python实现钢条切割问题与最长工公共序列问题

    #动态规划算法DP代码:

    #递归法计算斐波那契数列f(n)=f(n-1)+f(n-2)
    #递归算法-执行效率比较低,相同的问题算了好多遍—子问题的重新计算
    def fibnacci(n):
    if n==1 or n==2:
    return 1
    else:
    return fibnacci(n-1)+fibnacci(n-2)
    print(fibnacci(5))

    #非递归算法-执行效率高
    #动态规划DP思想=最优子结构,递推式子+重复子问题存储
    def fibnacci1(n):
    f=[0,1,1]
    if n>2:
    for i in range(n-2):
    num=f[-1]+f[-2]
    f.append(num)
    return f[n]
    print(fibnacci1(100))

    #钢条切割问题的递归算法
    from cal_time import *
    p=[0,1,5,8,9,10,17,17,20,21,23,24,26,27,27,28,30,33,36,39,40]
    P=[0,1,5,8,9,10,17,17,20,24,30]

    #使用递归的思想进行计算算法1
    #自定向顶上,时间复杂度度为O(2**n)
    def cut_rod_recurision(p,n):
    if n==0:
    return 0
    else:
    res=p[n]
    for i in range(1,n):
    res=max(res,cut_rod_recurision(p,i)+cut_rod_recurision(p,n-i))
    return res
    #使用递归的思想计算算法2
    def cut_rod_recurision2(p,n):
    if n==0:
    return 0
    else:
    res=0
    for i in range(1,n+1):
    res=max(res,p[i]+cut_rod_recurision2(p,n-i))
    return res

    #使用动态规划DP的思想实现钢条切割问题
    #自底向上思想
    @cal_time
    def cut_rod_DP(p,n):
    r=[0]
    for i in range(1,n+1):
    res=0
    for j in range(1,i+1):
    res=max(res,p[j]+r[i-j])
    r.append(res)
    return r[n]

    #输出解决方案的切割长度函数
    def cut_rod_extend(p,n):
    r=[0] #最优的解对应的值
    s=[0]
    for i in range(1,n+1):
    res_r=0 #记录价格的最优值
    res_s=0 #记录左边不切的部分的长度
    for j in range(1,i+1):
    if p[j]+r[i-j]>res_r:
    res_r=p[j]+r[i-j]
    res_s=j
    r.append(res_r)
    s.append(res_s)
    return r[n],s
    def cut_rod_solution(p,n):
    r,s=cut_rod_extend(p,n)
    ans=[]
    while n>0:
    ans.append(s[n])
    n-=s[n]
    return ans
    #递归算法输出函数运行时间需要进行函数的重新定义
    @cal_time
    def c1(p,n):
    return cut_rod_recurision(p,n)
    @cal_time
    def c2(p,n):
    return cut_rod_recurision2(p,n)

    print(c1(p,15))
    print(c2(p,20))
    print(cut_rod_solution(p,20))
    print(cut_rod_DP(p,20))
    #使用动态规划DP的思想实现最长公共子序列的问题
    #最长公共子序列问题
    #使用动态规划算法来进行解决
    def lcs_length(x,y):
    m=len(x)
    n=len(y)
    c=[[0 for _ in range(n+1)] for _ in range(m+1)] #创建一个m行n列的二维列表
    for i in range(1,m+1):
    for j in range(1,n+1):
    if x[i-1]==y[j-1]: #i,j的字符匹配的时候,来自于左上方的数值+1
    c[i][j]=c[i-1][j-1]+1
    else:
    c[i][j]=max(c[i-1][j],c[i][j-1])
    return c[m][n]

    def lcs(x,y):
    m = len(x)
    n = len(y)
    c = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
    b = [[0 for _ in range(n + 1)] for _ in range(m + 1)] #1为左上方,2上方,3左方
    for i in range(1,m+1):
    for j in range(1,n+1):
    if x[i-1]==y[j-1]: #i,j的字符匹配的时候,来自于左上方的数值+1
    c[i][j]=c[i-1][j-1]+1
    b[i][j]=1 #记录来自的方向
    elif c[i-1][j]>c[i][j-1]: #来自于上方
    c[i][j]=max(c[i-1][j],c[i][j-1])
    b[i][j]=2
    else:
    c[i][j] = max(c[i - 1][j], c[i][j - 1])
    b[i][j]=3
    return c[m][n],b
    #回溯法找回输出的最优方案
    def lcs_trackback(x,y):
    c,b=lcs(x,y)
    i=len(x)
    j=len(y)
    res=[]
    while i>0 and j>0:
    if b[i][j]==1: #来自左上方
    res.append(x[i-1])
    i=i-1
    j=j-1
    elif b[i][j]==2: #来自上方
    i-=1
    else: #来自左方
    j-=1
    return "".join(reversed(res))

    c,b=lcs("ABCBDAB","BDCABA")
    print(c)
    print(lcs_trackback("ABCBDAB","BDCABA"))
    
    




  • 相关阅读:
    Python 学习日记 第七天
    Python 学习日记 第六天
    Python 学习日记 第五天
    Python 学习日记 第四天
    Redis 中的数据类型及基本操作
    Asp.net mvc 中View 的呈现(二)
    Asp.net mvc 中View的呈现(一)
    Asp.net mvc 中Action 方法的执行(三)
    Asp.net mvc 中Action 方法的执行(二)
    Asp.net mvc 中Action 方法的执行(一)
  • 原文地址:https://www.cnblogs.com/Yanjy-OnlyOne/p/12457415.html
Copyright © 2011-2022 走看看