金矿题目

打印 上一主题 下一主题

主题 890|帖子 890|积分 2670

10.金矿题目

题目

有5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人人数也不同。例如有的金矿储量是500kg黄金,需要5个工人来挖掘,有的金矿储量是200kg黄金,需要3个工人来挖掘......
如果参与挖矿的工人的总数是10。每座金矿要么全挖,要么不挖,不能派出一半人挖取一半的金矿。要求计算出,最大挖取的黄金值。
  1. int[] g = {400, 500, 200, 300, 350};//金矿储量
  2. int[] p = {5, 5, 3, 4, 3};//挖取需要的工人数量
复制代码
思路

如果使用贪心算法,局部情况最优解,但是团体上却未必最优。好比,计算每个金矿的人均产值,为{80,100,66.6,75,116.6},单位是kg/人,每一步最优的话,就是挖取350/3人的金矿,和500/5人的金矿,然后就无法挖取了,这里挖取的金矿是850kg,但是还有比这个高的,400/5,500/5人的挖取就是900kg。
这里提供正确思路,其实这个题目,是典型的动态规划题目。动态规划就是把复杂的题目简化为规模较小的子题目,再从简朴的子题目自底向上的一步一步递推,最终得到复杂题目的最优解。
对于金矿,只有挖和不挖,两种选择。假设350kg/3人的,金矿不挖,题目就会转成10人挖前4个金矿的最优解,但是这个只是假设的最优,是否最优,还需要和挖350kg/3人的金矿,然后加上7个人挖前4个的金矿的最优解。比力那个大,那个就是最优解。这两种情况,就是全局题目的最优子结构。
就这样,对于每个金矿,都有挖和不挖,题目就一分为二,二分为四,一直把题目简化到0个金矿或0个工人时的最优选择,这个收益效果显然是0,也就是题目的边界。
这些就是动态规划的要点,确定题目的,全局最优解,和最优子结构之间的关系,以及题目的边界。这个关系用数学公式表达的话,就是状态转移方程式。
金矿数目为n,工人数目为w,金矿的含金量设为数组g[],金矿所需开采人数为p[]。设f(n,w)为n个金矿,w个工人时的最优收益函数,则该题目的状态转移方程式为,特别重要,后续2,3版本的代码,都要理解这个状态转移函数。
  1. f(n,w) = 0(n=0 或 w=0) //问题的边界
  2. f(n,w) = f(n-1,w) (n>=1,w<p[n-1]) //工人数量,不够挖取当前金矿
  3. f(n,w) = max(f(n-1,w),f(n-1,w-p[n-1]) + g[n-1]) (n >=1,w>=p[n-1]) //工人数量,可以挖取当前金矿
复制代码
代码

[code]//递归    /**     * 获取金矿最佳收益     *     * @param n 当前金矿数目     * @param w 当前工人人数     * @param g 金矿含量数组     * @param p 对应金矿含量所需人数数组     * @return 返回当前工人人数,和金矿数目的最佳收益函数     * 递归方式计算,的时间复杂度为O(2^n),适合于金矿数目小时的情况     * 注意这个n是当前金矿的数目,就好比每一个金矿都要分成2种情况,每个金矿下的其他金矿又有两种情况,组合起来看是一个满二叉树,     * 节点的个数和层级有关也就是金矿的数目有关为2^n(n为层级,这个题目中为金矿的个数)     */    public static int getBestGoldMining(int n, int w, int[] g, int[] p) {        if (n
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

杀鸡焉用牛刀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表