js实现动态规划 , 优化时间 , 优化空间
详情见小灰的算法之旅 , 以下是我个人的见解
题目:
很久很久以前,有一位国王拥有5座金矿,每座金矿的黄金储量不同,
需要参与挖掘的工人人数也不同。例如有的金矿储量是500kg黄金,需 要5个工人来挖掘;有的金矿储量是200kg黄金,需要3个工人来挖 掘…… 如果参与挖矿的工人的总数是10。每座金矿要么全挖,要么不挖,不能 派出一半人挖取一半的金矿。要求用程序求出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?
一开始的思路:
首先我们想到的是 : 求出每个金矿的性价比 , 从高到低依次挖出金矿
挖矿的性价比 : 350/3 > 500/5 > 200/3=300/4=400/5
那么我们十个人
- 先用
3 个人挖 350
的金矿 , - 再用
5 个人去挖 500
的金矿 , - 最后剩下
2 个人
不能再挖矿 - 此时我们的黄金数量是
850
这是否就是十个人能挖的最大黄金数量了呢 ? 答案不是
因为我们 用 5个人 去挖 500 的金矿 , 再用5个人去挖400的金矿 , 此时十个人刚好用完 , 并且黄金的数量是900
那么我们怎么才能获得黄金的最大数量呢 ? 这里就要引入动态规划来实现
动态规划就是把简单的问题转换成规模较小的子问题,再从简单的子问题自底向上一步一步递推,最终得到问题的最优解 , 这样说你可能还是云里雾里
其实我们算出做出每一个举动过后的结果 , 再和其它举动的结果做出比较 , 就可以计算出最好的结果 , 举个列子 :
p:[5,5,3,4,3], //金矿开采需要的工人数量
g:[500,400,350,300,200]//金矿储量
第一个500金矿我们可以挖也可以不挖
挖
: 黄金数量+500 , 工人数量 - 5-
接下来我们就用剩下的工人去挖下一个金矿 , 此时我们已经获得了500黄金
不挖
: 黄金数量 + 0 , 工人数量 - 0-
接下来我们就直接用不变的工人数量去挖下一个金矿
到第二个400金矿的时候
挖
: 黄金数量+400 , 工人数量 - 5-
此时已经没有工人 , 要加上第一次挖的500金矿 , 最终的黄金数量是900
不挖
: 黄金数量 + 0 , 工人数量 - 0-
到现在为止我们的工人数量和黄金数量都没有变化
一直这样遍历下去 , 直到工人数量为 零 或者 可以挖的黄金数量为 零 , 返回我们挖出的黄金数量
由题可知 , 我们创建几个变量 :
w
:工人的数量 ,n
:金矿的数量 ,
gold
:金矿和人数之间的关系(为了之后的思路比较清晰 , 我把这两个装到一个对象里面)
例如 : gold.g[0] 和 gold.p[0] 之间的关系就是 当金矿储量为 500 时需要 5 个人挖
w = 10 //工人的数量
n = 5 //金矿的数量
let gold = {
p:[5,5,3,4,3], //金矿开采需要的工人数量
g:[500,400,350,300,200]//金矿储量
}
一 . js实现动态规划
我们还要实现状态转移方程 :
- 金矿数量或者工人数量为
零
时 :F(n,w) = 0
- 工人的数量
不足以
挖当前的金矿时 , 去挖下一个金矿 :F(n-1 , w)
- 当前工人数量
足以
挖当前的金矿时 : (有两种选择)
- 挖:F(w-gold.p[n-1],n-1,gold)+gold.g[n-1]
- 不挖:F(w,n-1,gold)
- 返回第三种情况的最大值
Math.max(F(w,n-1,gold),F(w-gold.p[n-1],n-1,gold)+gold.g[n-1])
let w = 10//工人数量
let n = 5 //可选金矿数量
let gold = {
p:[5,5,