紧接着上一篇动态规划问题,现在我们开始探讨一个新的问题,问:有一个发现了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. AAC DRC

    DRC feature 在AAC decoder是optional.DRC info是在编码在fill element. Program reference level是进行DRC的一个参考值.是原始 ...

  2. 一起了解 .Net Foundation 项目 No.4

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. BenchmarkDotN ...

  3. Lenet 神经网络-实现篇(2)

    Lenet 神经网络在 Mnist 数据集上的实现,主要分为三个部分:前向传播过程(mnist_lenet5_forward.py).反向传播过程(mnist_lenet5_backword.py). ...

  4. mysql中的文件排序(filesort)

    在MySQL中的ORDER BY有两种排序实现方式: 1. 利用有序索引获取有序数据 2. 文件排序 在explain中分析查询的时候,利用有序索引获取有序数据显示Using index ,文件排序显 ...

  5. c# pcm

    using System; using System.IO; using System.Text; using System.Windows.Forms; using System.Runtime.I ...

  6. pyqt5 通过QLinearGradient 绘制取色板

    要绘制HSV取色板,一般通过绘制前景色和背景色的方式实现,先绘制前景,然后绘制背景,前景是HSV颜色空间,从左到右,背景是亮度,从上到下,xs和ys是鼠标的当前的位置. def graphicsVie ...

  7. 开源协议:LGPL协议、OSGi协议

    本文介绍开源的协议. LGPL 是 GNU Lesser General Public License (GNU 宽通用公共许可证)的缩写形式,旧称 GNU Library General Publi ...

  8. Foreach报错

    List<String> a = new ArrayList<String>(); 2 a.add("1"); 3 a.add("2") ...

  9. Spring Boot框架 - application.properties配置

    阅读此文章之前,需要参考 https://www.cnblogs.com/mysummary/p/12238242.html 创建Spring Boot项目 建成后目录如下 一.在com.demo.s ...

  10. 批处理设置IP

    @echo off title 静态IP设置 set netName=本地连接 set address=192.168.1.202 netsh netsh interface ipv4 set dns ...