紧接着上一篇动态规划问题,现在我们开始探讨一个新的问题,问:有一个发现了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. HTTP头部字段总结【转】

    原作者: 留七七, 地址:http://www.jianshu.com/p/6e86903d74f7 一.常用标准请求头字段 Accept  设置接受的内容类型 Accept-Charset    设 ...

  2. js Array 的所有方法

    下面的这些方法会改变调用它们的对象自身的值: Array.prototype.copyWithin()  在数组内部,将一段元素序列拷贝到另一段元素序列上,覆盖原有的值. Array.prototyp ...

  3. Gym安装ubuntu16.04

    Step1:将gym克隆到计算机上: git clone https://github.com/openai/gym.git 如果你的电脑没有安装git,那么键入 sudo apt install g ...

  4. Abp.Core运行时提示XX没有实现,或者没有依赖注入的问题,或者调试时提示做出更改的问题

    因为abp的web层对application层有项目引用,但是对domain层并不存在项目引用,而是bin目录下直接引用的dll文件,所以当domain层修改后不会自动将dll文件同步过去.所以有时候 ...

  5. drf框架,restful接口规范,源码分析

    复习 """ 1.vue如果控制html 在html中设置挂载点.导入vue.js环境.创建Vue对象与挂载点绑定 2.vue是渐进式js框架 3.vue指令 {{ }} ...

  6. mybatis--MyBatis动态SQL语句

    mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类: 1. if 语句 (简单的条件判断) 2. ...

  7. Java - Test - TestNG: Idea 引入 testng.xml 自动生成插件

    1. 概述 Idea 引入自动生成 testng.xml 插件 自动生成 testng.xml 2. 背景 testng 调试 调试 testng, 主要是这两种方法 ide 下直接执行测试 方法 类 ...

  8. 每天进步一点点------H.264学习 (一)

    分三个阶段学习1.第一个阶段: 学习H.264,首先要把最基本最必要的资料拿在手里.这些资料包括:标准文档+测试模型+经典文章,在本FTP中能找到.首先看 <H.264_MPEG-4 Part ...

  9. 每天进步一点点------时序分析基础与时钟约束实例(四)IO口时序(Input Delay /output Delay)

    1.1  概述 在高速系统中FPGA时序约束不止包括内部时钟约束,还应包括完整的IO时序约束和时序例外约束才能实现PCB板级的时序收敛.因此,FPGA时序约束中IO口时序约束也是一个重点.只有约束正确 ...

  10. win api 音频可视化

    暂时记录,改天有时间再完善...其实写好好久了,但以前的代码丢了,重新写一遍.. 原理和 python 的一样,获取输入设备,然后把数据读取到 buffer 中,在绘制出来. 这里要注意两点: 1. ...