动态规划算法-02矿工挖矿问题

版权声明:转载请注明出处 https://blog.csdn.net/zhouchen1998/article/details/88742619

矿工挖矿问题

  • 简述
    • 为了解决在给定金矿和矿工数量的前提下,能够获得最多黄金的挖矿策略。
    • 很多算法题其实就是这个问题换了一个情境。
  • 问题描述
    • 有5个金矿,每个金矿黄金储量不同,需要参与挖掘的工人数目也不同,假定有10个工人,每个金矿要么全挖,要么不挖,不可以拆分,试问,想得到最多的黄金,应该选择挖取哪几个金矿。
    • 金矿信息如下表。
      金矿编号 黄金储量 所需工人数目
      1 400 5
      2 500 5
      3 200 3
      4 300 4
      5 350 3
  • 问题分析
    • 如果要使用动态规划解题,就要确定动态规划的三要素:最优子结构、边界和状态转移函数。
    • 最优子结构
      • 解题目标是确定10个工人挖5个金矿能够获得最多的黄金量,该问题可以从10个工人挖4个金矿的子问题中递归求解。
      • 在解决10个工人挖4个金矿时,存在两种选择,一种是放弃第5个矿,将10个工人投入到挖四个矿中;另一种选择是决定对第5个矿进行挖掘,因此需要从这10个人中抽取3个人(第5个矿需要人数)加入第5个矿开采,剩余的人处理前4个矿。
      • 因此,最优解应该是这两种选择中获得黄金数量较多的那一种。
      • 为了描述方便,设金矿数量为n,工人个数为w,第n个矿的黄金数量为G(n),第n个矿所需工人为P(n),要想获得10个矿工挖掘5个金矿的最优解为max(F(4,10),F(4,10-P[4])+G[4])。
      • 这就是最优子结构
    • 边界
      • 对于一个金矿而言,若当前的矿工数量不能达到金矿的挖掘需要,则获得的黄金数量为0,若能满足矿工数量要求,获得的黄金数量为G[0]。
      • 因此,边界可以描述为
        • n=1,w>=P[0]时,F(n,w)=G[0]
        • n=1,w<P[0]时,F(n,w)=0
    • 状态转移函数
      • 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])
    • 到这里,三要素找到了,经过这个过程也明白了求解过程,由底向上计算,一步步推导可以得到结果,换句话说,n步的解其实就是第一步的结果推来的,这就是递归过程。
  • 代码
    •   def gold_mining(n ,w, G, P):
            """
            利用递归实现动态规划算法过程
            :param n:
            :param w:
            :param G:
            :param P:
            :return:
            """
            if n <= 1 and w < P[0]:
                return 0
            if n == 1 and w >= P[0]:
                return G[0]
            if n > 1 and w < P[n-1]:
                return gold_mining(n-1, w, G, P)
            if n > 1 and w >= P[n-1]:
                return max(gold_mining(n-1, w, G, P), gold_mining(n-1, w-P[n-1], G, P) + G[n-1])
        
        
        if __name__ == '__main__':
            G = [400, 500, 200, 300, 350]
            P = [5, 5, 3, 4, 3]
            n = 5
            w = 10
            print(gold_mining(n, w, G, P))
      
  • 补充说明
    • 具体代码可以查看我的Github,欢迎Star或者Fork
    • 参考书《你也能看得懂的Python算法书》,书中略微有一点不合理之处,做了修改
    • 到这里,其实你已经体会到了动态规划的简约之美,当然,要注意Python是有递归深度限制的,如不是必要,建议使用循环控制

猜你喜欢

转载自blog.csdn.net/zhouchen1998/article/details/88742619