动态规划最通俗的讲解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/forestForQuietLive/article/details/82843700

小灰和小黄的讲解 :https://www.sohu.com/a/153858619_466939

一、连接问题---------上台阶问题(10层台阶,每次只能走 1个或者2个台阶,一共有多少种走法?)

1、问题建模         (动态规划的三个重要概念:最优子结构、边界、状态转移公式

2、求解问题

最优子结构:F(10)= F(9)+ F(8)

状态转移方程:F(N) = F(N-1) + F(N-2)

边界:F(0) = 0; F(1) = 1; F(2) = 2

'''
最简单的版本 时间复杂度O(2的n次方),空间复杂度O(1)
'''
def getClimbingWays_1(n):
    if n<1:
        return 0
    elif n==1:
        return 1
    elif n==2:
        return 2
    else:
        return getClimbingWays_1(n-1)+getClimbingWays_1(n-2)

'''
用字典形式实现备忘录的算法 时间复杂度O(n),空间复杂度O(n)
'''
dict1 = {} #存储每一个F(n)对应的值,防止重复计算

def getClimbingWays_2(n):
    
    #存储每一个F(n)对应的值,防止重复计算
    global dict1 
    if n < 1:
        return 0
    elif n==1:
        return 1
    elif n==2:
        return 2
    else:
        pass
    if dict1.keys==n:
        return dict1[n]
    else:
        temp = getClimbingWays_2(n-1)+getClimbingWays_2(n-2)
        dict1[n] = temp
        return temp

'''
非递归实现方法,时间复杂度O(N),空间复杂度均为O(1)
'''
def getClimbingWays_3(n):
    if n<1:
        return 0
    elif n==1:
        return 1
    elif n==2:
        return 2
    else:
       pass
    a=1
    b=2
    for i in range(3,n+1):
       temp = a+b;a=b;b=temp
    return temp

二、金矿问题

问题描述:有一个国家发现了5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人数也不同。参与挖矿工人的总数是10人。每座金矿要么全挖,要么不挖,不能派出一半人挖取一半金矿。要求用程序求解出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?

边界条件:

F(n,w) = 0 (n<=1, w<p[0]);

F(n,w) = g[0] (n==1, w>=p[0]);

状态转换方程:

F(n,w) = F(n-1,w) (n>1, w<p[n-1])

F(n,w) = max(F(n-1,w), F(n-1,w-p[n-1])+g[n-1]) (n>1, w>=p[n-1])

import numpy as np

#设置第一个值为0,方便金矿和人数的index从1开始
golds = [0,400,500,200,300,350]
peoples = [0,5,5,3,4,3]

'''
Input:
    10个人:w表示
    5金矿: n表示
    golds[]: 存储每个金矿对应的金额
    peoples[]: 存储每个金矿所需的人数
Output:
结果(最大金额)
'''
def get_mostGold(n,w,golds,peoples):

    #构建矩阵,(1 row,11列),index:从1开始
    preresults = np.zeros(w+1).astype(int)
    results = preresults.copy().astype(int)

    #填充第一行的值(第一个金矿对应1-10人的情况)
    for i in range(1,w+1):
        if i < peoples[1]:
            preresults[i] = 0
        else:
            preresults[i] = golds[1]

    for i in range(2,n+1):
        for j in range(1,w+1):
            # 状态转移方程
            if j < peoples[i]:
                # F(n, w) = F(n - 1, w)(n > 1, w < p[n])
                results[j] = preresults[j]
            else:
                # F(n, w) = max(F(n - 1, w), F(n - 1, w - p[n]) + g[n])(n > 1, w >= p[n])
                pre = preresults[j]
                cur = preresults[j - peoples[i]] + golds[i]
                results[j] = pre if pre > cur else cur
        preresults = results.copy()
    return preresults[w]
ans = get_mostGold(5,10,golds,peoples)
print(ans)

 

展开阅读全文

没有更多推荐了,返回首页