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

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(使用前将#替换为@)

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

  • 如何开始使用 Chainsaw for Log4j?

    我想开始使用 Chainsaw v2 几乎没有关于它的信息 我只找到了this http www velocityreviews com forums t140105 help using chainsaw for log4j html 但
  • 无法使用 json 架构验证器根据预定义的 yaml 文件验证查询参数

    我需要根据预定义的 yaml 文件架构验证查询参数的架构 因此我使用 json 架构验证器 验证如何失败 我正在执行以下步骤 填充参数和相应的架构 final List
  • Spring3/Hibernate3/TestNG:有些测试给出 LazyInitializationException,有些则没有

    前言 我在单元测试中遇到了 LazyInitializationException 的问题 而且我很难理解它 正如你从我的问题中看到的那样Spring 中的数据库会话 https stackoverflow com questions 13
  • RMI 中的引用传递问题? [复制]

    这个问题在这里已经有答案了 有人可以告诉我我错在哪里 为什么这个 RMI 聊天应用程序不起作用 目标是通过远程对象或序列化对象实现客户端 服务器和逻辑之间的解耦 import javax swing import java awt even
  • java.lang.LinkageError:尝试重复的类定义

    为什么会发生错误以及如何修复它 02 13 02 pool 4 thread 2 WARN Exception in thread pool 4 thread 2 02 13 02 pool 4 thread 2 WARN java lan
  • 字符串池可以包含两个具有相同值的字符串吗? [复制]

    这个问题在这里已经有答案了 字符串池可以包含两个具有相同值的字符串吗 String str abc String str1 new String abc Will the second statement with new operator
  • Java Microsoft Excel API [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何导入 org.apache.commons.lang3.ArrayUtils;进入 Eclipse [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我如何导入 org apache commons lang3 ArrayUtils 将库添加到 Ecl
  • 容器中的 JVM 计算处理器错误?

    最近我又做了一些研究 偶然发现了这一点 在向 OpenJDK 团队抱怨之前 我想看看是否有其他人观察到这一点 或者不同意我的结论 因此 众所周知 JVM 长期以来忽略了应用于 cgroup 的内存限制 众所周知 现在从 Java 8 更新某
  • 所有平台上的java

    如果您想用 java 为 Windows Mac 和 Linux 编写桌面应用程序 那么所有这些代码都相同吗 您只需更改 GUI 即可使 Windows 应用程序更像 Windows 等等 如果不深入细节 它是如何工作的 Java 的卖点之
  • 如何将 Observable>> 转换为 Observable>

    我陷入了如何将以下可观察类型转换 转换为我的目标类型的困境 我有以下类型的可观察值 Observable
  • 在 Java 中将弯音发送到 MIDI 音序器

    我了解启动和运行 MIDI 音序器的基础知识 并且希望能够在播放过程中增加 减小序列的音高 但弯音是发送到合成器而不是音序器的消息 我尝试将音序器的接收器设置为合成器的发射器 当我发送弯音短消息时 音序器保持相同的音调 但随后合成器以新的弯
  • Java:java.util.ConcurrentModificationException

    我正在制作 2D 目前正在研究用子弹射击 子弹是一个单独的类 所有项目符号都存储在称为项目符号的数组列表中 当它超出屏幕一侧 Exception in thread main java util ConcurrentModification
  • 创建正则表达式匹配数组

    在Java中 我试图将所有正则表达式匹配返回到一个数组 但似乎您只能检查模式是否匹配某些内容 布尔值 如何使用正则表达式匹配来形成与给定字符串中的正则表达式匹配的所有字符串的数组 4城堡的回答 https stackoverflow com
  • Android Gradle 同步失败:无法解析配置“:classpath”的所有工件

    错误如下 Caused by org gradle api internal artifacts ivyservice DefaultLenientConfiguration ArtifactResolveException Could n
  • 了解 Spark 中的 DAG

    问题是我有以下 DAG 我认为当需要洗牌时 火花将工作划分为不同的阶段 考虑阶段 0 和阶段 1 有些操作不需要洗牌 那么为什么 Spark 将它们分成不同的阶段呢 我认为跨分区的实际数据移动应该发生在第 2 阶段 因为这里我们需要cogr
  • 为什么我的代码会产生错误:该语句没有返回结果集[重复]

    这个问题在这里已经有答案了 我正在从 Microsoft SQL Server Studio 执行以下查询 该查询工作正常并显示结果 SELECT INTO temp table FROM md criteria join WHERE us
  • 警告:无法更改每个人的权限:

    当运行 Java 快速入门示例时https developers google com drive web quickstart java hl hu https developers google com drive web quicks
  • 春季 CORS。在允许的来源中添加模式

    查看CORS的弹簧指南 以下代码启用所有允许的来源 public class MyWebMVCConfigurer extends WebMvcConfigurerAdapter Override public void addCorsMa
  • 为什么应该首选 Java 类的接口?

    PMD https pmd github io 将举报以下违规行为 ArrayList list new ArrayList 违规行为是 避免使用 ArrayList 等实现类型 而是使用接口 以下行将纠正违规行为 List list ne

随机推荐

  • 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 每