紧接着上一篇动态规划问题,现在我们开始探讨一个新的问题,问:有一个发现了5个金矿,每一个金矿的储量不同,需要参与挖掘的工人数也不通,参与挖矿工人的总数量是10人,每一座金矿要么全挖,要么不挖,不能派一般人挖一半的金矿,想要得到最多的黄金,应该挖取哪几座金矿呢?金矿1储存500金 需5人,金矿2储存400金需要5人,金矿3储存350金矿需要3人,金矿4储存300人需要4人,金矿5储存200金需要3人

经过上篇爬楼梯的问题,我们已经知道了动态规划的三个核心元素,最优子结构、边界、状态转移方程式,好现在我们就开始分析一下看在五个金矿全部在的情况下 可以分为两个状态1、第五金矿不挖、前四个金矿中挖两个,2第五个金矿选择挖,和前四个金矿选择挖一个 同时人数剩余7人。这个两个结构都是这个大问题的最优子结构 但是这个最优子结构和这个金矿选择有什么关于呢?没错 就是两者选其中最大的一个。

我们将金矿数设置为N,工人数为W,金矿的数量设置为数组G[],金矿的用工量设置为数组p[]。则得到结论:

  F(5,10)=MAX(F(4,10),F(4,10-P[4])+G[4])

ok 现在我们 找到了最优子结构和和状态转移方程式,但是程序的边界是什么呢?这个很简单边界就是只剩下一个金矿可以选择我们必须挖这个唯一的金矿,但是这个时候我们需要满足一个 条件就是剩余的总人数大于挖改矿需要的人数。

同样我们和上篇文章一样我们可以首先开始递归算法。

1、递归算法

/**
*
* @param G 金矿储存量
* @param N 金矿数
* @param W 工人数
* @param P 需要的挖矿人数
* @return
*/
public int getKingGold(int G[],int N,int W,int P[])throws Exception{
if (N>G.length)throw new Exception("金矿数不匹配!");
if(N<=1 && P[0] > W) return 0; //当数量人数少于 需要挖矿的人数时
if (N==1 && P[0]<=W) return G[0]; //最后一个矿时 人数多于需要挖矿的人数
if (N>1 && W < P[N-1])return getKingGold(G,N-1,W,P);
int num1 = getKingGold(G,N-1,W,P);
int num2 = getKingGold(G,N-1,W-P[N-1],P) + G[N-1];
return Math.max(num1,num2);
}

2、备忘录算法


这里要做一个小改动,应为这个是要记录,将剩余人数和剩余金矿数作为的最大值记录下来

public int getKingGoldwithMap(int G[],int N,int W,int P[],Map<Integer,Integer> map)throws Exception{
if (N>G.length)throw new Exception("金矿数不匹配!");
if(N<=1 && P[0] > W) return 0; //当数量人数少于 需要挖矿的人数时
if (N==1 && P[0]<=W) return G[0]; //最后一个矿时 人数多于需要挖矿的人数
if (N>1 && W < P[N-1])return getKingGold(G,N-1,W,P);
DicText obj = new DicText(N,W);
if (map.containsKey(obj.hashCode())){
return map.get(obj.hashCode());
}else{
int num1 = getKingGold(G,N-1,W,P);
int num2 = getKingGold(G,N-1,W-P[N-1],P) + G[N-1];
int result = Math.max(num1,num2);
map.put(obj.hashCode(),result);
return result;
} } private static class DicText{
private int n;
private int w; @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DicText dicText = (DicText) o;
return n == dicText.n &&
w == dicText.w;
} @Override
public int hashCode() {
final int seed = 31;
int num = seed * n +2 ;
num = num * w + 1;
return num;
} public DicText(int n, int w) {
this.n = n;
this.w = w;
} public int getN() {
return n;
} public void setN(int n) {
this.n = n;
} public int getW() {
return w;
} public void setW(int w) {
this.w = w;
}
};

 这里将金矿剩余数和人数的剩余数加在一起做成一个类,并将hashcode值进行重写。

三、动态规划的解法

代码为

public int getMostGold(int n,int w,int []g,int[] p){
int perReuslts []=new int[p.length];
int result [] = new int [p.length];
//填充边界格子的值
for (int i = 0;i<=n ;i++){
if (i<p[0]){
perReuslts[i] = 0;
}else {
perReuslts[i] = g[0];
}
}
//填充其余格子的值,外层循环是金矿的数量,内层循环是人工数
for (int i = 0;i<n ;i++){
for (int j = 0;j<=w;j++){
if (j<p[i]){
result[j] = perReuslts[j];
}else {
result[j] = Math.max(perReuslts[j],perReuslts[j-p[i]] + g[i]);
}
}
}
return result[n];
}

  根据表中的数据可以找到以上规律 可以求出数据。

动态规划-国王的金矿问题java的更多相关文章

  1. 动态规划入门——数字三角形(Java)

    动态规划的概念对于新手来说枯燥难懂,就算看懂了,做题的时候依旧抓耳挠腮的毫无头绪,这些比较难理解的算法,还是需要根据例子来一步步学习和理解,从而熟练掌握,下面,咱们就通过一个简单的小例子来学习动态规划 ...

  2. 【Leetcode】国王挖金矿

    参考该文章 https://www.cnblogs.com/henuliulei/p/10041737.html #include <iostream> #include <cstr ...

  3. 动态规划算法的java实现

    一:动态规划 1)动态规划的向前处理法 java中没有指针,所以邻接表的存储需要转化一中形式,用数组存储邻接表 用三个数组u,v,w存储边,u数组代表起点,v数组代表终点,w代表权值;例如:1--&g ...

  4. Java面试题集(136-150)

    摘要:目,尽管仅仅有15道题目.可是包括的信息量还是非常大的,非常多题目背后的解题思路和算法是非常值得玩味的. 136.给出以下的二叉树先序.中序.后序遍历的序列? 答:先序序列:ABDEGHCF.中 ...

  5. 算法-动态规划DP小记

    算法-动态规划DP小记 动态规划算法是一种比较灵活的算法,针对具体的问题要具体分析,其宗旨就是要找出要解决问题的状态,然后逆向转化为求解子问题,最终回到已知的初始态,然后再顺序累计各个子问题的解从而得 ...

  6. java 递归打印20个斐波那契数

    class Test { public static void main(String[] args) { // feibo j=new feibo(); for (int n = 1; n < ...

  7. Java匹马行天下之 Java国出了个Java——举国欢庆

    Java帝国的崛起 前言: 看庭前花开花落,宠辱不惊, 望天上云卷云舒,去留无意. 闹心的事儿,选择释怀: 纠缠的人儿,试着放下, 生活其实很美. 心若向阳,就无惧悲伤. 愿你明朗坦荡纵情豁达,有得有 ...

  8. Java匹马行天下之Java帝国的崛起(大结局)

    Java匹马行天下之Java帝国的崛起大结局 前言: [博客*缘] 网络真情伴, 博客友谊连. 笑中藏泪暖中寒. 回想那些悲喜, 苦涩也缠绵. 往事难回首, 新篇染旧言. 世间多少梦能全. 感谢相牵, ...

  9. Java刷题-tree

    一.分别按照二叉树先序,中序和后序打印所有的节点. 这道题就是书上的算法思想的实际使用,唯一需要特别注意到的是用递归的方式建树,还是比较巧妙的,因为一棵树的建立过程字符流是重复使用的,用递归的方式对根 ...

随机推荐

  1. winform学习(6)控件的对齐、比例、定位操作

    窗体控件的常用操作 选中一个控件,按住Ctrl再点选另一个控件(此时编辑的是第二个控件,当使用框选选中多个控件时,编辑的是黑色锚点的控件) 代码中的居顶和居底: 控件标识符.BringToFront( ...

  2. STA之PVT

    在STA星球,用library PVT.RC corner跟OCV来模拟这些不可控的随机因素.在每个工艺结点,通过大量的建模跟实测,针对每个具体的工艺,foundary厂都会提供一张推荐的timing ...

  3. MinGW dll导入导出类

    dll不仅可以导入导出函数,还可以导入导出类.这篇文章就来介绍如何将类导入dll中并导出. 首先我们建立一个名为dll.cpp的文件(又是这种破名字),里面写上: #include <iostr ...

  4. Web 安全工具篇:Burp Suite 使用指南

    真的是一点都不过分,了解详情请继续往下读. Burp Suite 介绍 Burp Suite 是用于攻击 web 应用程序的集成平台.它包含了许多工具,并为这些工具设计了许多接口,以促进加快攻击应用程 ...

  5. 搭建私人通讯录/日历同步服务_使用cardDAV/calDAV服务

    搭建私人通讯录/日历同步服务_使用cardDAV/calDAV服务 转载注明来源: 本文链接 来自osnosn的博客,写于 2020-02-18. Radicale, Radicale (对cardd ...

  6. [Reversal 剧情设计] 序言

    想开发一个图形游戏已经很久了,这个寒假好不容易学了一些OpenGL知识,初步具备了开发图形游戏的能力,我觉得我可以开始了.当然,我的游戏并不是冷冰冰的PVE,肯定还需要一些剧情丰富色彩. 本来我的游戏 ...

  7. c++调用自己编写的静态库(通过eclipse)

    转:https://blog.csdn.net/hao5335156/article/details/80282829 参考:https://blog.csdn.net/u012707739/arti ...

  8. ES6 Set和Map的那点事

    Set  1.Set特点 类数组 新增数据结构 是构造函数 成员值唯一  注重独一无二的特征 2.Set实例的常用方法 console.log('------------Set操作方法-------- ...

  9. IDE - IDEA - 快捷键整理 - 01. Navigation

    1. 概述 工具的熟练程度, 会决定工作效率 总共也就 140 条左右吧 需要讲解吗? 2. ref 1. idea 自带的 ReferenceCard.pdf 3. keymap 1. 文件移动 C ...

  10. 【资源分享】Half-Life(半条命)中英版

    *----------------------------------------------[下载区]----------------------------------------------* ...