文章目录

  • 黄金矿工
    • 解题思路
    • 递归实现
    • 二维数组实现
    • 一维数组实现

黄金矿工

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

解题思路

动态规划:

对于最后的金矿,都有挖或者不挖的选项:

对比两种情况的收益,最终可得到最大收益。

①400kg/5人②500kg/5人③200kg/3人④300kg/4人⑤350kg/3人

如何确定挖不挖⑤:比较a.10个人挖前4个的收益和b.7个人挖前4个的收益+⑤的收益

  • 10个人挖4座的收益

    • 10个工人在前3个金矿中做出最优选择。

    • 6(10-4=6)个工人在前3个金矿中做出最优选择。

  • 7个人挖4座

    • 7个工人在前3个金矿中做出最优选择。

    • 3(7-4=3)个工人在前3个金矿中做出最优选择

依次类推,把问题依次拆分。一直把问题简化成在0个金矿或0个工人时的最优选择,这个收益结果显然是0,也就是问题的边界 。

设金矿数量为n,工人数为w,金矿开采需要的工人数量为数组p,金矿储量为数组g,获得的收益为F(n,w)

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

F(n,w)=0(n=0或w=0)F(n,w) = 0 (n=0或w=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) = F(n-1,w) (n≥1, w<p[n-1]) 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,p>=p[n−1])F(n,w)=max(F(n-1, w), F(n-1, w-p[n-1]+g[n-1)]) (n>= 1, p>=p[n-1]) F(n,w)=max(F(n−1,w),F(n−1,w−p[n−1]+g[n−1)])(n>=1,p>=p[n−1])

递归实现

/*** @param w 工人数量* @param n 金矿数量* @param p 金矿开采需要的工人数量* @param g 金矿储量* @return 最优*/// 时间复杂度O(2^n)
public static int getBestGoldMining(int w, int n, int[] p, int[] g) {if (w == 0 || n == 0) {return 0;}if (w < p[n - 1]) {return getBestGoldMining(w, n - 1, p, g);}return Math.max(getBestGoldMining(w, n - 1, p, g),getBestGoldMining(w - p[n - 1], n - 1, p, g) + g[n - 1]);
}

二维数组实现


从上图可发现在递归的时候出现了很多次的重复调用,为解决此问题我们可选择一个二维数组来记录中间数据,如下:

使用上面的方程填满这张表就可以得出最终数据:

/*** 获得金矿最优收益** @param w 工人数量* @param p 金矿开采需要的工人数量* @param g 金矿储量* @return 最大收益*/
public static int getBestGoldMining(int w, int[] p, int[] g) {// 创建表格int[][] resultTable = new int[g.length + 1][w + 1];// 填充表格 i个金矿for (int i = 1; i <= g.length; i++) {// j个人for (int j = 1; j <= w; j++) {if (j < p[i - 1]) {resultTable[i][j] = resultTable[i - 1][j];} else {// 1、不挖当前金矿int v1 = resultTable[i - 1][j];// 2、挖当前金矿int v2 = resultTable[i - 1][j - p[i - 1]] + g[i - 1];// 3、比较两种情况的收益resultTable[i][j] = Math.max(v1, v2);}}}//返回最后1个格子的值return resultTable[g.length][w];
}

一维数组实现

在上面方法的循环中我们可以发现每次计算其实只用到了上一行的数据,因此,无论金矿有多少座,我们只保存1行的数据即可。在计算下一行时,要从右向左统计,把旧的数据一个一个替换掉。

public static int getBestGoldMiningV2(int w, int[] p, int[] g) {//创建当前结果int[] results = new int[w + 1];//填充一维数组for (int i = 1; i <= g.length; i++) {// 在计算下一行时,要从右向左统计for (int j = w; j >= 1; j--) {if (j >= p[i - 1]) {// 1、不挖当前金矿int v1 = results[j];// 2、挖当前金矿int v2 = results[j - p[i - 1]] + g[i - 1];// 3、比较两种情况的收益results[j] = Math.max(results[j], results[j - p[i - 1]] + g[i - 1]);}} }//返回最后1个格子的值return results[w];
}

从右向左原因:在计算v2值时,要获取上一行的旧数据(比当前下标小),如果从左往右统计,当前位置左侧的数据已经全是本行的新数据,获取不到上一行的旧数据导致结果错误

黄金矿工问题【动态规化】相关推荐

  1. 动态规化 - 最小编辑距离

    最小编辑距离(Minimum Edit Distance) 参考:https://web.stanford.edu/class/cs124/lec/med.pdf 目标(objective):给定两个 ...

  2. 用Java写个小游戏--黄金矿工代码实现

    黄金矿工 项目结构 前期准备 Stone类 Gold类(包含Gold类,GoldMini类,GoldPlus类) GameWin类 Line类 Parent类 Sky类 项目结构 GameWin类,游 ...

  3. 清华鲁继文团队提出DynamicViT:一种高效的动态稀疏化Token的ViT

    [导读] 由于随着ViT中的token数量的增长,会导致计算成本呈平方级急剧增加!近期,清华黄高团队提出了自适应序列长度的DVT方案,本篇文章,我们将介绍另一种方法.6月3日,清华鲁继文教授团队提出了 ...

  4. 动态子类化CComboBox以得到子控件EDIT及LISTBOX

    动态子类化CComboBox以得到子控件EDIT及LISTBOX Joise.LI写于2004-4-6 ComboBox是比较常用的一个控件,有三种样式:CBS_SIMPLE(简单),CBS_DROP ...

  5. 黄金矿工游戏demo

    试玩地址:  http://www.adanghome.com/js_demo/13/ 请使用chrome.firefox或safari.ie的话,请大于ie8. 按空格键扔出钩子,按左右键控制矿工移 ...

  6. 还在用全部token训练ViT?清华UCLA提出token的动态稀疏化采样,降低inference时的计算量...

    关注公众号,发现CV技术之美 本文分享一篇由清华& UCLA联合研究的论文『DynamicViT: Effificient Vision Transformers with Dynamic T ...

  7. 2018级C语言大作业 - 黄金矿工

    黄金矿工 C语言作业 分享18级同学大一上学期用C语言实现的黄金矿工.分步骤代码.图片音乐素材.可执行程序可从百度网盘下载: 链接:https://pan.baidu.com/s/1xCy1l2-7Q ...

  8. 【源码+教程】Java课设项目_12款最热最新Java游戏项目_Java游戏开发_Java小游戏_飞翔的小鸟_王者荣耀_超级玛丽_推箱子_黄金矿工_贪吃蛇

    马上就要期末了,同学们课设做的如何了呢?本篇为大家带来了12款热门Java小游戏项目的源码和教程,助力大家顺利迎接暑假![源码+教程]Java课设项目_12款最热最新Java游戏项目_Java游戏开发 ...

  9. 你的记忆里有黄金矿工吗?

    黄金矿工是大概是我初中时候玩的游戏吧,记忆中的样子是一群人围在一个电脑傍边,两人一组,输了就换下一组,虽然它不上现在游戏的丰富的游戏内容.但是就是让人欲罢不能,成为一款经典! Java游戏项目黄金矿工 ...

最新文章

  1. (九)单片机串行口 内部结构的讲解 01
  2. Android -- queryIntentActivities
  3. 【Web】Rest API 验证授权如何做?
  4. VC++读取txt文件指针的变化
  5. Unable to open the physical file XXX.mdf
  6. Alibaba-AndFix Bug热修复框架原理及源码解析
  7. Python实现模板
  8. how to create Employee in SAP Cloud Platform
  9. 修改mysql的my.ini文件,导致mysql服务1067启动失败的解决方法
  10. MySQL基础 - 注意事项
  11. 创建华丽 UI 的 7条规则 第一部分 (2019年更新)
  12. CVPR2021 Oral|开放世界中的目标检测
  13. Java开发 明华usbkey_明华驱动官方版下载-明华usbkey数字证书驱动下载v3.0.2420.9 最新版-当易网...
  14. 黑群晖DSM7.1.0物理机安装教程
  15. Python每日一记20哑变量
  16. Java根据word模板生成word文件
  17. Php区分自然量跟aso量,ASO优化师该如何判断做优化时下载量与评论的比例关系
  18. 【基于MATLAB的数字图像处理】第四章·图像增强
  19. JavaScript 基础学习(三)
  20. esp32烧录的时候出现报错Chip sync error :Failed to connect to ESP32: Timed out waiting for packet heade

热门文章

  1. 【TRIO-Basic从入门到精通教程十七】设置连接TRIO运动控制器并输入激活码
  2. 6款经典图表软件推荐
  3. 超低功耗/抗干扰19*4段LCD液晶显示驱动IC-VKL076SSOP28 I2C通讯接口 小体积封装 FAE支持
  4. HDU6589 NTT
  5. python聊天室详细教程_python简单实现聊天室功能(代码教程)
  6. QQ阅读器技术框架解析之一《代码预览和分析》
  7. VS中的经典字体推荐
  8. 树莓派sd卡格式化_树莓派安装免费IP电话系统3CX
  9. matlab实验7绘图操作绘制三维曲线,matlab上机习题6 MATLAB7.0三维绘图
  10. 好用的截图软件Ashampoo Snap Corporate