问题描述:

很 久 很 久 以 前, 有 一 位 国 王 拥 有 5 座 金 矿, 每 座 金 矿 的 黄 金 储 量 不 同, 需 要 参 与 挖 掘 的 工 人 人 数 也 不 同。 例 如 有 的 金 矿 储 量 是 500kg黄 金, 需 要 5 个 工 人 来 挖 掘; 有 的 金 矿 储 量 是 200kg 黄 金, 需 要 3 个 工 人 来 挖 掘…… 如 果 参 与 挖 矿 的 工 人 的 总 数 是 10。 每 座 金 矿 要 么 全 挖, 要 么 不 挖, 不 能 派 出 一 半 人 挖 取 一 半 的 金 矿。 要 求 用 程 序 求 出, 要 想 得 到 尽 可 能 多 的 黄 金, 应 该 选 择 挖 取 哪 几 座 金 矿?

动态规划思想:

动 态 规 划, 就 是 把 复 杂 的 问 题 简 化 成 规 模 较 小 的 子 问 题, 再 从 简 单 的 子 问题自 底 向 上 一 步 一 步 递 推, 最 终 得 到 复 杂 问 题 的 最 优 解。

对 于 问 题 中 的 金 矿 来 说, 每 一 个 金 矿 都 存 在 着“ 挖” 和“ 不 挖” 两 种 选 择。让 我 们 假 设 一 下, 如 果 最 后 一 个 金 矿 注 定 不 被 挖 掘, 那 么 问 题 会 转 化 成 什 么 样 子 呢? 显 然, 问 题 简 化 成 了 10 个 工 人 在 前 4 个 金 矿 中 做 出 最 优 选 择。

相 应 地, 假 设 最 后 一 个 金 矿 一 定 会 被 挖 掘, 那 么 问 题 又 转 化 成 什 么 样 子 呢?由 于 最 后 一 个 金 矿 消 耗 了 3 个 工 人, 问 题 简 化 成 了 7 个 工 人 在 前 4 个 金 矿 中 做 出 最 优 选 择。

这 两 种 简 化 情 况, 被 称 为 全 局 问 题 的 两 个 最 优 子 结 构。 究 竟 哪 一 种 最 优 子 结 构 可 以 通 向 全 局 最 优 解 呢? 换 句 话 说, 最 后 一 个 金 矿 到 底 该 不 该 挖 呢? 那 就 要 看 10 个 工 人 在 前 4 个 金 矿 的 收 益, 和 7 个 工 人 在 前 4 个 金 矿 的 收 益 + 最 后 一 个 金 矿 的 收 益 谁 大 谁 小 了。

状 态 转 移 方 程 式:

我 们 把 金 矿 数 量 设 为 n, 工 人 数 量 设 为 w, 金 矿 的 含 金 量 设 为 数 组 g[], 金 矿 所 需 开 采 人 数 设 为 数 组 p[], 设 F( n, w) 为 n 个 金 矿、 w 个 工 人 时 的 最 优 收 益 函 数, 那 么 状 态 转 移 方 程 式 如 下。

问 题 边 界, 金 矿 数 为 0 或 工 人 数 为 0 的 情 况。

F( n, w) = 0 (n = 0 或 w = 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])

递归实现:

//递归实现public static int gbgm1(int n,int w,int[] p, int[] g){if(n ==0 || w == 0){return 0;}if(w < p[n-1]){return gbgm1(n-1,w,p,g);}else{return Math.max(gbgm1(n-1,w ,p,g),gbgm1(n-1,w - p[n-1],p,g)+g[n-1]);}}

递归实现会造成大量的空间浪费与时间消耗,有大量重复的计算

因此创建一个中间表来存储结果,自底向上去计算。

非递归实现:

//自底向上,改为非递归实现public static int gbgm2(int w,int[] p, int[] g){int[][] result = new int[w+1][w+1];for(int i = 1; i <= g.length;i++){for(int j = 1; j <= w;j++){if(j < p[i-1]){//i 是金矿编号,p[i-1] 即为挖取i号金矿需要的工人result[i][j] = result[i-1][j];}else {result[i][j] = Math.max(result[i-1][j],result[i-1][j-p[i-1]]+g[i-1]);}}}return result[g.length][w];}

以上代码仍有优化空间,可以优化存储,因为当前行的计算结果只依赖上一行结果,所以可以创建一维数组,从后往前计算,防止覆盖掉上一行数据,从而节省空间的消耗

优化:

//优化空间public static int gbgm3(int w,int[] p, int[] g){int[] result = new int[w+1];for(int i = 1; i <= g.length; i++){for (int j = w; j >= 1; j--){//从后面往前去计算结果,不会覆盖掉数据,可以依据上一次的计算结果得出该行结果if(j >= p[i-1]){result[j] = Math.max(result[j],result[j-p[i-1]]+g[i-1]);}}}return result[w];}

动态规划:挖金矿问题相关推荐

  1. java回调函数的生命_Java车票,车站,生命周期,龟兔赛跑,同步锁,礼让,守护线程,挖金矿【诗书画唱】...

    个人理解:加同步锁等的时候,就可以让线程"按顺序排队",一个一个地抢CPU,一个抢完对应的每次有的CPU了,另一个才抢对应的每次有的CPU,解决"并发"问题等. ...

  2. 百度上线百度金矿,个人电脑也可以挖金矿

    百度金矿号称一个可以让个人电脑利用闲置网络资源赚钱的软件,这种软件近几年好几家公司都有做过尝试,迅雷,小米等互联网公司都有搞过. 这种模式有点像比特币不过之前有试过迅雷的确实不太理想,百度金矿也只是 ...

  3. 人工智能变现难?这家AI挖金矿公司已上市

    "变现"是当下阶段人工智能公司面临最重要的难题,表面看来人工智能已经在安防.医疗.教育.智能手机.汽车.金融等诸多行业纷纷落地,但这些行业实际上能产生的营收并不十分乐观.而且诸多均 ...

  4. 【动态规划模型】金矿模型理解动态规划!(精彩的故事)

    对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本 ...

  5. 【转载】通过金矿模型介绍动态规划 (动态规划入门)

    先附上原文地址:http://www.cnblogs.com/sdjl/articles/1274312.html 通过金矿模型介绍动态规划 对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第 ...

  6. 动态规划入门之国王的金矿

    最近学习算法,对动态规划不太了解,使用的时候照搬转移方程式,知其然不知其所以然,今天看到一篇动态规划的教程,解释得非常通俗,原文在这里[动态规划入门教程] (http://blog.csdn.net/ ...

  7. 【面试经典】求解金矿问题(动态规划初级)

    问题:有一个国家发现了5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人数也不同(情况如下图) 金矿编号 黄金储量 需要人数 1 400 5 2 500 5 3 200 3 4 300 4 5 35 ...

  8. 通过金矿模型介绍动态规划

    对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本 ...

  9. 通过金矿模型介绍动态规划(经典入门)

    对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本 ...

  10. 动态规划--金矿模型

    对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本 ...

最新文章

  1. 波涛汹涌的黄金甲,一碗中药引发的血案!
  2. IOS 消息机制(NSNotificationCenter)
  3. 在FCKeditor 2.6中添加插入视频和音频功能(最新修订版)
  4. 马云:未来无工可打,人工智能发展红利还在10年以后
  5. Android之让图片匀速旋转效果
  6. 书评:JBoss AS 7:配置,部署和管理
  7. 关于Mysql5.5在关键字方面的变化
  8. FISCO BCOS 控制台 call调用已经部署的合约 不存在does not exist
  9. 记一次被200G流量 DDOS攻击的处理经验
  10. wireshark抓包:分析阿里小蜜网络通信方式
  11. zabbix监控WEB页面及告警 实战
  12. python二维码加动态图_用python自制个性二维码(设置带LOGO的二维码带动图)
  13. 大数据专业该学习什么?
  14. Swift5.1 语言指南(三) 快速之旅
  15. 双向链表插入、删除操作
  16. OVS 内核CT实现
  17. 星际争霸2 微操练习 地图
  18. it Ebook 免费
  19. Java可变长参数列表
  20. axis=0 与 axis=1 的区分

热门文章

  1. github恢复误删除的文件
  2. python实现12306抢票,春节不用担心买不到票回家了
  3. DNS域传送漏洞(CVE-2015-5254)
  4. 浅谈西门子840d主轴速度控制_西门子 840D 数控系统故障诊断与维修
  5. centos7安装polygraph
  6. 五分钟看懂vue路由守卫
  7. c++小游戏:笨鸟先飞(Flappy bird hhh)
  8. 这几个解决D5渲染器崩溃闪退的方法,一定要试试
  9. 编写程序:5类员工有对应封装类,创建Employee数组,若干不同的Employee对象,并实现增删改查功能(《黑马程序员》P144编程题加强版)
  10. Mac上的网络视频会议软件