动态规划经典例题-国王的金矿问题

2023-11-11

金矿问题

问题概述:
有一位国王拥有5座金矿,每座金矿的黄金储量不同,
需要参与挖掘的工人人数也不同。例如有的金矿储量是500kg黄金,需 要5个工人来挖掘;有的金矿储量是200kg黄金,需要3个工人来挖 掘…… 如果参与挖矿的工人的总数是10。每座金矿要么全挖,要么不挖,不能 派出一半人挖取一半的金矿。要求用程序求出,要想得到尽可能多的黄 金,应该选择挖取哪几座金矿?
什么是动态规划:
动态规划:将复杂问题简化为规模较小的子问题,再从简单的子问题自底向上一步一步递推,最终得到复杂问题的最优解
思路:
利用动态规划思想将大问题拆分为一个个小问题,之后一步一步解决问题
例:
在这里插入图片描述
如此直至人数为0或者剩余金矿数为0,也就是问题的边界
之后自底向上就可以从小问题的最优解求出整体的最优解,使利益最大化
具体解释与步骤详情参考代码

package algorithm;

/**
 * 动态规划金矿问题
 * 如何在已有人数和金矿收益情况下获得最大的淘金收益
 *  动态规划:将复杂问题简化为规模较小的子问题,
 *      再从简单的子问题自底向上一步一步递推,最终得到复杂问题的最优解
 *  动态规划的要点:
 *      确定全局最优解与最优子结构间的关系
 *      确定问题的边界
 */
public class GoldMining {
    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(g.length,w,p,g));
        System.out.println("最优收益为:"+getBestGoldMining2(g.length,w,p,g));
        System.out.println("最优收益为:"+getBestGoldMining3(g.length,w,p,g));
    }

    /**
     * 此方法采用递归方式计算每种最优子结构的收益情况,递归到问题的边界即可用人数为0,或者剩余矿数为0
     * 缺点:
     *  会进行许多的重复计算,每次都分2种最优子结构,时间复杂度为O(2^n)
     * @param n 总金矿数
     * @param w 总可用人数
     * @param p 每个金矿需要人数
     * @param g 每个金矿的收益
     */
    public static int getBestGoldMining(int n,int w,int[] p,int[] g){
       if(w==0 || n==0){
           return 0;
       }
       //如果当前可用人数不足以挖当前矿,则换个矿,n-1代表当前矿
       if(w<p[n-1]){
           return getBestGoldMining(n-1,w,p,g);
       }
       /**
        * 如果当前矿可以挖,则选取两个最优子结构(挖当前矿,不挖当前矿)中收益高的方法
        * n-1 代表除去当前矿,去后一个矿查看
        * w-p[n-1] 代表挖当前矿后剩下的人数
        */
        return Math.max(getBestGoldMining(n-1,w,p,g),(getBestGoldMining(n-1,w-p[n-1],p,g)+g[n-1]));
    }

    /**
     *  根据自底向上求解的步骤,采用一张表记录计算结果,避免重复计算
     *  时间与空间复杂度都是O(n*w)
     * @param n
     * @param w
     * @param p
     * @param g
     */
    public static int getBestGoldMining2(int n,int w,int[] p,int[] g){
        //使用二维数组表示表,纵轴是金矿信息,横轴是人数信息
        int[][] resultTable = new int[n+1][w+1];
        //填充表格
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= w; j++) {
                //当前人数不足以挖g[i-1]矿,就把获得收益置为不挖当前矿的收益
                if(j<p[i-1]){
                    resultTable[i][j] = resultTable[i-1][j];
                }else{
                    /**
                     * 可以挖当前矿,取挖矿与不挖矿的最优解
                     * resultTable[i][j]就代表当前矿的最大收益 = max(不挖当前矿去查看之后的收益,挖当前矿查看之后的收入并加上当前矿的收入)
                     * 为什么resultTable[i][j]后面的却是resultTable[i-1][j-p[i-1]]+g[i-1]
                     * 因为当前循环是从1开始的,g中的i-1、p中的i-1都其实代表的是当前矿的信息
                     */
                    resultTable[i][j] = Math.max(resultTable[i-1][j],resultTable[i-1][j-p[i-1]]+g[i-1]);
                }
            }
        }
        //最后一个格子就是最优收益
        return resultTable[g.length][w];
    }
    /**
     * 以上方法的空间复杂度仍有可以优化的余地
     * 根据Math.max(resultTable[i-1][j],resultTable[i-1][j-p[i-1]]+g[i-1]);我们可以发现我们当前的最优解都是根据上一行推导而来
     * 故我们可以只用一行表格来代替整个表格,可以看出每次都是i-1使用左边的数据,所以我们从右边替换数据即可
     * 以下代码我们相当于明面只保留了人数的横坐标,实际用两重for循环保证了还是二维的表格,只是节省了空间
     */
    public static int getBestGoldMining3(int n,int w,int[] p,int[] g){
        int[] resultTable = new int[w+1];
        for (int i = 1; i <= n; i++) {
            for (int j = w; j >=1; j--) {
                if(j>=p[i-1]){
                    //左边的resultTable[j]是i号金矿时的收益,而右边则相当于是i-1号矿收益因为还未被覆盖
                    resultTable[j] = Math.max(resultTable[j],resultTable[j-p[i-1]]+g[i-1]);
                }
            }
        }
        return resultTable[w];
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态规划经典例题-国王的金矿问题 的相关文章

  • 多线程环境下如何更好的使用ExecutorService?

    我需要创建一个库 其中包含同步和异步方法 executeSynchronous 等待直到有结果 返回结果 executeAsynchronous 立即返回一个 Future 如果需要 可以在其他事情完成后进行处理 我的图书馆的核心逻辑 客户
  • 使用 AbstractTableModel 获取 JTable 中选定的行

    我有一个JTable using AbstractTableModel我在哪里有一个JCheckBox在第一列中用于选择行 现在 我需要从已检查的表中获取选定的行 现在 我按顺序从第一行遍历到最后一行并获取所有选择的行 如下所示 List
  • 在 IntelliJ 上进行 Google App Engine Java 开发?

    令人烦恼的是 Google App Engine 已成为其中的另一个项目 他们只发布 Eclipse 插件 如 Spring Webflow 而我更喜欢 IntelliJ 你能用IntelliJ成功运行本地测试环境吗 并调试 部署本地或实时
  • 线程“main”java.lang.UnsatisfiedLinkError中出现异常:java.library.path中没有opencv_java249

    我目前正在尝试在我的 32 位笔记本电脑上设置 OpenCV 但我不断收到一条令我困惑的错误消息 Exception in thread main java lang UnsatisfiedLinkError no opencv java2
  • 在 TestNG 中运行多个类

    我正在尝试自动化一个场景 其中我想登录一次应用程序 然后进行操作而无需再次重新登录 考虑一下 我有在特定类的 BeforeSuite 方法中登录应用程序的代码 public class TestNGClass1 public static
  • 如何将自定义日志处理程序添加到 Google App Engine?

    我正在尝试向我的 java 应用程序添加自定义日志处理程序 我已经实现了一个扩展 java util Logging Handler 类的 InnerLogger 类 在我的logging properties中声明为处理程序 handle
  • Java 唤醒休眠线程

    我阅读了其他帖子 但没有找到我正在寻找的确切答案 所以我希望有人能给出一些澄清 我有一个将运行一段时间的程序 我有一些在后台运行的线程来执行各种任务 为了简单起见 让我们考虑 3 个线程 ThreadA每 10 秒执行一次任务 其中Thre
  • Java 泛型:如何为泛型类型指定类类型?

    我有一个 POJO 指定为 MyClass u where U是泛型类型参数 我正在尝试编写一个接受类引用的实用方法Class u
  • 不要模拟值对象:过于通用的规则,没有解释

    以下是 Mockito 单元测试框架的引用 不要模拟值对象 为什么有人会想要这样做呢 因为实例化对象太痛苦了 gt 无效 原因 如果创造新的装置太困难 那就是一个迹象 代码可能需要一些认真的重构 另一种方法是创建 价值对象的构建者 有一些工
  • Java:使用 Java.util.concurrent 线程访问读取线程串行端口

    我正在尝试编写一个 Java 串行设备驱动程序并想使用 对我来说是新的 java util concurrent包裹 我有一种发送数据包然后等待 ACK 的方法 我打算有炭 接收在不同的线程中运行 如果接收线程收到 ACK 它应该使用发送数
  • 在 eclipse 之外将 Spring MVC 应用程序部署到 tomcat 的幕后会发生什么?

    我猜想使用像 eclipse 这样很棒的 IDE 的一个缺点是你会忽略应用程序幕后发生的事情 我是一名 Ruby 开发人员 所以不是一名 Java 老手 所以我一直在用 java 编写一个项目 并使用 spring 框架进行 IOC 和 M
  • 如何从 Google Custom Search API 获取超过 100 个结果

    我正在尝试使用 Google Custom Search API 在 Java 中进行研究 因此 我需要为每个查询提供一个大的结果集 然而 我似乎仅限于前 100 个结果 这比我需要的要少得多 我使用这样的列表方法 list setStar
  • 抽象类或接口。哪种方式是正确的?

    有两种方法可以选择抽象类或接口 微软解决方案和Oracle解决方案 微软 设计指南 请使用抽象 在 Visual Basic 中为 MustInherit 类而不是接口来将协定与实现分离 http msdn microsoft com en
  • 使用Java开发跨平台,不同平台字体缩放不同

    我正在为我的大学制作一些软件 需要一个 GUI 在它的第一个版本中 我让它使用系统外观 因此它看起来像 Linux Mac Windows 中的本机应用程序 我发现这很麻烦 因为我必须根据操作系统使所有 JLabel 具有不同的大小 无论分
  • HTTP PUT 在 Java 中上传文件

    Edit 我想我已经弄清楚如何执行二进制数据部分 仔细检查代码 但我很确定我做对了 现在 当我尝试按照中所述完成上传时遇到新错误Vimeo API 文档 http vimeo com api docs upload streaming Ed
  • 读/写带有特殊字符的.txt文件

    I open Notepad Windows 并写 Some lines with special characters Special 并前往另存为 someFile txt 与Encoding set to UTF 8 在Java中我有
  • 如果抛出RuntimeException,是否可以将其作为异常捕获?

    如果我有一个try抛出一个块RuntimException子类 可以是后续的catch块将其捕获为Exception 具体来说 public class MyAppException extends RuntimeException In
  • 方法签名中带或不带synchronized关键字的方法具有相同的字节码

    对于以下 2 个类 获得相同的 Java 字节码 java版本 java 版本 1 8 0 181 Java TM SE 运行时环境 构建 1 8 0 181 b13 Java HotSpot TM 64 位服务器 VM 内部版本 25 1
  • 如何从spark中的hbase表中获取所有数据

    我在 hbase 中有一个大表 名称为 UserAction 它具有三个列族 歌曲 专辑 歌手 我需要从 歌曲 列族中获取所有数据作为 JavaRDD 对象 我尝试了这段代码 但效率不高 有更好的解决方案来做到这一点吗 static Spa
  • 编写自定义 Eclipse 调试器

    EDIT 一定有某种方法可以解决这个问题 而无需编写全新的调试器 我目前正在研究在现有 java 调试器之上构建的方法 如果有人对如何获取 Java 调试器已有的信息 有关堆栈帧 变量 原始数据等 有任何想法 那将非常有帮助 我想要做的是我

随机推荐

  • dockerfile创建lnmp镜像

    目录 一 创建lnmp的相关镜像 1 1 dockerfile创建php7 2 16镜像 1 2 dockerfile创建nginx 1 15 7镜像 1 3 mysql镜像是直接在docker仓库上pull 二 通过dockerpose
  • 串口服务器网页进不去怎么办,路由器登录入口进不去怎么办?

    问 路由器登录入口进不去怎么办 答 如果在设置路由器的时候 进不去路由器的登录入口 无法对路由器进行设置 这多半是用户自己操作有误导致的 也可能是路由器或者其它客观原因引起的 具体的解决办法如下 温馨提示 1 如果是用手机设置路由器时 手机
  • clang 01.clang简介

    文章目录 前言 1 Clang的工作流程 前言 Clang的官方网站是 http clang llvm org 它被认为是C家族的LLVM前端 Clang可能指代三种不同的实体 前端 由Clang程序库实现 编译器驱动器 由Clang命令和
  • 本机如何传文件到VMware 中

    本机传文件到VMware 中可以使用2种方法 1 安装tools 直接拖拽过去 2 实现文件共享 在VMware中没有安装解压文件的应用时 使用tools会不再适用 这时可以选择共享文件夹的方式 直接在本机解压文件 共享文件夹到VMware
  • C#中的Dispose模式

    声明 本文中的内容属于个人总结整理而来 个人水平有限 对于部分细节难免有理解错误及遗漏之处 如果您在阅读过程中有所发现 希望您能指正 同时文章中的部分内容也参考了其它大神的文章 如果文章中的内容侵犯了您的权益 表示非常歉意 请您指出 我将尽
  • C++职工管理系统

    C 演讲比赛流程管理系统 1 职工管理系统的需求 2 功能实现 2 1 创建管理类 2 2退出功能 2 3增加联系人信息 2 4显示职工信息 2 5删除离职职工 2 6修改职工信息 2 7查找职工信息 2 8按照编号排序 2 9清空所有文档
  • access建立er图_5G SA注册流程(2)- RRC连接建立

    导读 在正式讨论SA注册的相关NAS流程之前 笔者觉得有必要先讨论下SA下的RRC连接的建立流程 毕竟这是终端与网络交互的连接基础 同时也会讨论下不同场景下的RRC建立流程中信令内容的异同 RRC连接建立流程 SA注册流程主要是终端与5GC
  • 8X8X8光立方整体框架设计&技术细节

    从一师兄那拿来的 东西是师兄自己做的 觉得特有才一人 只是进了互联网公司 感觉做嵌入式更适合他 Powered by lihui Liusheng 2012 Shenyang 太过技术了 写给自己留着看的 不懂的可绕行 确实有些头大 在对最
  • OA权限树搭建 代码

    ul ul
  • Android下拉刷新效果实现

    本文主要包括以下内容 自定义实现pulltorefreshView 使用google官方SwipeRefreshLayout 下拉刷新大致原理 判断当前是否在最上面而且是向下滑的 如果是的话 则加载数据 并更新界面 自定义实现pulltor
  • Matlab中dir使用中遇到的一些问题

    今天调程序时遇到一个bug 感觉有点意思 也许有人会遇到类似的问题吧 问题 说手上有一段代码 原本是希望在一个文件夹中读取出其中所有音频文件的 tdir dir fullfile SoundDir SoundFileName NumSoun
  • 出现command 'gcc' failed with exit status 1 解决方案

    在centos7 上用pip 安装psutil的时候很不幸的出现了如下错误 pip install psutil Collecting psutil Using cached psutil 5 3 1 tar gz Installing c
  • python 角度判断_大牛带你打牢Python基础,看看这10语法

    都说Python简单 易懂 但是有时候却又很深奥 许多人都觉的自己学会了 却老是写不出项目来 对很多常用包的使用也并不熟悉 学海无涯 我们先来了解一些Python中最基本的内容 1 数值 数值包括整型和浮点型 分别对应整数和浮点数 后者精度
  • Python3 列表笔记

    列表 使用 括起来的一个个元素的集合 1 列表的元素使用 进行分割 2 列表的元素可以是任意数据类型 1 创建列表 list huarzil 32 3 14 True zhuangsan lisi 32 29 30 name height
  • linux学习笔记--网络编程

    目录 概念 协议 网络应用设计模式 分层模型 协议格式 TCP状态 网络名词 socket编程 套接字 字节序 函数 socket bind listen accept connect C S模型 server client 封装 高并发服
  • iview 数据表格 固定列拉倒底部后刷新出现错行问题

    很多小伙伴肯定遇到过这个组件问题 下面只需要一行即可搞定 vue方法 首先我们在mixin js里封装一个方法 pageSizeChange pageSize 每页显示数量变更 this searchParams limit pageSiz
  • C#中,浮点数的比较和decimal

    浮点数 C 的浮点数类型 float double 当我们定义一个浮点数可以 可以使用var 关键字 可以做类型推断 定义float类型 数字末尾需要加上 F或者是f 定义一个double类型 double a1 1 1 var a2 1
  • <转>企业应用架构 --- 分层

    系统架构师 基础到企业应用架构 分层 上篇 一 前言 大家好 接近一年的时间没有怎么书写博客了 一方面是工作上比较忙 同时生活上也步入正轨 事情比较繁多 目前总算是趋于稳定 可以有时间来完善以前没有写完的系列 也算是对自己这段时间工作和生活
  • 程序流程图是什么?基本流程图讲解

    程序流程图是什么 程序流程图是流程图的其中一种分类 又称程序框图 指用特定图形符号加上对应的文字描述表示程序中所需要的各项操作或判断的图示 程序流程图除了说明程序的流程顺序外 着重于说明程序的逻辑性 一 程序流程图特点 当程序流程中有较多循
  • 动态规划经典例题-国王的金矿问题

    金矿问题 问题概述 有一位国王拥有5座金矿 每座金矿的黄金储量不同 需要参与挖掘的工人人数也不同 例如有的金矿储量是500kg黄金 需 要5个工人来挖掘 有的金矿储量是200kg黄金 需要3个工人来挖 掘 如果参与挖矿的工人的总数是10 每