题目

很久很久以前,有一位国王拥有5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人人数也不同。例如有的金矿储量是500kg黄金,需要5个工人来挖掘:有的金矿储量是200kg黄金,需要3个工人来挖掘…

如果参与挖矿的工人的总数是10。每座金矿要么全挖,要么不挖,不能派出一半人挖取一半的金矿。要求用程序求出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?

总共10个工人,A:400kg黄金/5人 B:500kg黄金/5人 C:200kg黄金/3人 D:300kg黄金/4人 E:350kg黄金/3人

n/w 1个工人 2个工人 3个工人 4个工人 5个工人 6个工人 7个工人 8个工人 9个工人 10个工人
400kg黄金/5人
500kg黄金/5人
200kg黄金/3人
300kg黄金/4人
350kg黄金/3人
  • 解决方法

    1. 贪心算法:依次求得局部最优解,最终得到全局最优解

      1. 按照金矿的性价比从高到低进行排序,有限选择性价比最高的金矿来挖掘,然后选择性价比第2的…
      2. 按照贪心算法的思路得出来的最佳金矿收益是350+500即850kg黄金
        == 按照这种想法是局部最优,但是全局未必是最优的
    2. 动态规划:把复杂的问题简化成规模较小的子问题,再从简单的子问题自底向上一步一步递推
      动态规划的要点:确定全局最优解和最优子结构之间的关系,以及问题的边界

      原问题分解成子问题进行求解(类似于背包问题

  • 动态规划的状态转移方程式

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

    F(n,w) = 0 (n=0或w=0)

    问题边界,金矿数为0或工人数为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])

    在常规情况下,具有两种最优子结构(挖当前金矿或不挖当前金矿)。

  • 相同的颜色代表了方法被传入相同的参数

  • 自底向上求解

w < p[n-1] : F(n,w)= F(n-1,W) (n≥1, w<p[n-1])
w ≥ p[n-1] : F(n,w) = max(F(n-1,w), F(n-1,w-p[n-1])+g[n-1])

例如:F(2,10) = max(F(2-1,10),F(2-1,10-5)+500) = max(F(1,10),F(1,5)+500) = max(400,400+500) = 900

n/w 1个工人 2个工人 3个工人 4个工人 5个工人 6个工人 7个工人 8个工人 9个工人 10个工人
400kg黄金/5人 0 0 0 0 400 400 400 400 400 400
500kg黄金/5人 0 0 0 0 500 500 500 500 500 900
200kg黄金/3人 0 0 200 200 500 500 500 700 700 900
300kg黄金/4人 0 0 200 300 500 500 500 700 800 900
350kg黄金/3人 0 0 350 350 500 550 650 850 850 900
  • 代码实现
package some_problem;
/*** Copyright (C), 2019-2020* author  candy_chen* date   2020/7/30 16:00* version 1.0* Description: 测试*//****/
public class GetBestGoldMining {/*** 获得金矿最优收益* @param w 工人数量* @param n 可选金矿数量* @param p 金矿开采所需的工人数量* @param g 金矿储量* @return*///递归进行求解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*///递归做了很多重复的计算,当金矿越来越多,递归层次越来越深,重复调用也就越来越多,无谓的调用必然会降低程序的性能//利用双循环来填充一个二维数组,时间复杂度和空间复杂度都是O(nw)public static int getBestGoldMiningV2(int w,int[] p,int[] g){//创建表格int[][] resultTable = new int[g.length+1][w +1];//填充表格for (int i =1;i<= g.length;i++){for (int j=1;j<=w;j++){if (j<p[i-1]){resultTable[i][j] = resultTable[i-1][j];}else{resultTable[i][j] = Math.max(resultTable[i-1][j],resultTable[i-1][j-p[i-1]] + g[i-1]);}}}//返回最后1个格子的值return resultTable[g.length][w];}// 并不需要保存整个表格,无论金矿多少座,我们只保存1行的数据即可,在计算下一行时,要从右向左统计,把旧的数据一个一个替换掉//时间复杂度是O(nw) 空间复杂度是O(n)/*** 获得金矿最优收益* * @param w 工人数量* @param p 金矿开采所需的工人数量* @param g 金矿数量* @return*/public static int getBestGoldMiningV3(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]){results[j] = Math.max(results[j],results[j-p[i-1]] + g[i-1]);}}}//返回最后一个格子的值return results[w];}public static void main(String[] args) {int w = 10;int[] p = {5,5,3,4,3};int[] g = {400,500,200,300,350};System.out.println("最优收益:" + getBestGoldMining(w,g.length,p,g));}
}

说明:作者根据网络资料进行搜索学习,理解整理 若有侵权联系作者
参考:程序员小灰

LeetCode题解:如何求解金矿问题(动态规划)相关推荐

  1. LeetCode题解 - 动态规划-股票买卖

    LeetCode题解 - 动态规划-股票买卖 文章目录 LeetCode题解 - 动态规划-股票买卖 **一.穷举框架** **二.状态转移框架** **三.秒杀题目** 121. 买卖股票的最佳时机 ...

  2. leetcode 题解 (500-1000题,持续更新,part 2)

    part1(1-500), part3(1000-*) 502. IPO 题意:给定k,w,profits数组和capital数组.k表示最多可完成的任务数.w是初始资本.profits是各个任务的收 ...

  3. LeetCode部分习题解答记录-动态规划

    LeetCode部分习题解答记录-动态规划 动态规划 120.三角形最小路径和 方法:递归+记忆化 方法2:DP 64.最小路径和 方法1:递归 方法2:DP 从终点到起点,逐步更新 从起点到终点,逐 ...

  4. leetcode题解131-分割回文串

    问题描述 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 .返回 s 所有可能的分割方案. 回文串 是正着读和反着读都一样的字符串. 示例 1: 输入:s = "aa ...

  5. 算法与数据结构+LeetCode题解-Js版

    LeetCode题解Js版 https://webbj97.github.io/leetCode-Js/ 题外话 LeetCode题解:传送门 前端笔记:传送门 项目背景 旨在提高自己对算法的理解,将 ...

  6. 【LeetCode题解】347_前K个高频元素(Top-K-Frequent-Elements)

    更多 LeetCode 题解笔记可以访问我的 github. 文章目录 描述 解法一:排序算法(不满足时间复杂度要求) Java 实现 Python 实现 复杂度分析 解法二:最小堆 思路 Java ...

  7. 900 多道 LeetCode 题解,这个 GitHub 项目值得 Star!

    转自 | 码农有道 大家好,我是小 G. 周末风和日丽,适合刷 LeetCode 今天给你们推荐个 GitHub 项目,里面收集了 900 多道 LeetCode 题解,并包含中英文两个版本,适合大多 ...

  8. PHP版Leetcode题解开始随缘更新

    2019独角兽企业重金招聘Python工程师标准>>> PHP版Leetcode题解 我叫skys215,是一名bug工程师. 我接触编程的时间比较早,但是因为我数学不好加上比较懒, ...

  9. [LeetCode 题解]: Binary Tree Preorder Traversal

    前言 [LeetCode 题解]系列传送门:  http://www.cnblogs.com/double-win/category/573499.html 1.题目描述 Given a binary ...

  10. LeetCode 题解汇总

    为什么80%的码农都做不了架构师?>>>    LeetCode 题解汇总 转载于:https://my.oschina.net/michao/blog/801863

最新文章

  1. 跟刘强东、雷军等大佬聊天后,我总结了:如何结交牛人,跟大咖做朋友!
  2. AI领域的人才短缺,原因是什么?该如何解决?
  3. Java学习_day004:Scanner与分支结构
  4. 0-100之间的素数、判断素数的基本和优化方法
  5. 每秒8.8亿次请求!让数据存得起,看得见 - 云原生多模数据库Lindorm 2020双十一总结
  6. 【MFC】带下拉菜单的工具栏
  7. 适用于高级Java开发人员的十大书籍
  8. 【LeetCode笔记】剑指 Offer 59 - II. 队列的最大值(Java、辅助队列)
  9. python access 源码_连接的微软Access数据库,这是一个轻量级的Python模块(MDB格式)...
  10. Adobe Reader PDF 护眼设置
  11. [bzoj4945][Noi2017]游戏
  12. NDP调查:P2P下载的视频中60%为情色内容
  13. ROS 端口IP映射 动态IP映射
  14. 电源控制环稳定性基础理论与调试方法
  15. Vultr与阿里云结合自动换IP的解决方案
  16. 仿支付宝输入密码效果
  17. 关于使用手机电池替换3节干电池的尝试
  18. 什么是机器学习?简单理解
  19. C# Chart 波形显示,动态数据滑动显示方法
  20. 苹果如何做ASO优化?优化的主要思路有哪些?

热门文章

  1. 安装ubuntu20.04, CUDA11.4, cnDNN, tensorflow, pytorch
  2. CAD编辑器图片转换为CAD的方法
  3. 第二届 “国信蓝点”软件设计大赛 C语言模拟题(附程序题 解题程序)
  4. 业务流程图怎么画?3步+8张案例,5分钟教你快速上手!
  5. 关于排列组合的一点点自己的见解
  6. ROS | Gazebo仿真—阿克曼(Ackermann)四轮小车模型
  7. 解决win10(联想电脑)自动删除一些破解文件
  8. O2OA V4.3763 稳定版发布,Java 办公开发平台迎来大量更新
  9. 【渝粤题库】广东开放大学 形成性考核 - 副本 (13)
  10. Linux -- Ubuntu 修改Home目录下的中文目录为英文