题目
很久很久以前,有一位国王拥有5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人人数也不同。例如有的金矿储量是500kg黄金,需要5个工人来挖掘:有的金矿储量是200kg黄金,需要3个工人来挖掘…
如果参与挖矿的工人的总数是10。每座金矿要么全挖,要么不挖,不能派出一半人挖取一半的金矿。要求用程序求出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?
总共10个工人,A:400kg黄金/5人 B:500kg黄金/5人 C:200kg黄金/3人 D:300kg黄金/4人 E:350kg黄金/3人
n/w | 1个工人 | 2个工人 | 3个工人 | 4个工人 | 5个工人 | 6个工人 | 7个工人 | 8个工人 | 9个工人 | 10个工人 |
---|---|---|---|---|---|---|---|---|---|---|
400kg黄金/5人 | ||||||||||
500kg黄金/5人 | ||||||||||
200kg黄金/3人 | ||||||||||
300kg黄金/4人 | ||||||||||
350kg黄金/3人 |
-
解决方法:
-
贪心算法:依次求得局部最优解,最终得到全局最优解
- 按照金矿的性价比从高到低进行排序,有限选择性价比最高的金矿来挖掘,然后选择性价比第2的…
- 按照贪心算法的思路得出来的最佳金矿收益是350+500即850kg黄金
== 按照这种想法是局部最优,但是全局未必是最优的
-
动态规划:把复杂的问题简化成规模较小的子问题,再从简单的子问题自底向上一步一步递推
动态规划的要点:确定全局最优解和最优子结构之间的关系,以及问题的边界原问题分解成子问题进行求解(类似于背包问题)
-
-
动态规划的状态转移方程式:
我们把金矿数量设为n,工人数量设为w,金矿的含金量设为数组g[ ],金矿所需开采人数设为数组p[ ]. 设F(n, w)为n个金矿、w个工人时的最优收益函数,那么状态转移方程式如下。
F(n,w) = 0 (n=0或w=0)
问题边界,金矿数为0或工人数为0的情况。
F(n,w)= F(n-1,W) (n≥1, w<p[n-1])
当所剩工人不够挖掘当前金矿时,只有一种最优子结构。
F(n,w) = max(F(n-1,w), F(n-1,w-p[n-1])+g[n-1]) (n≥1, w≥p[n-1])
在常规情况下,具有两种最优子结构(挖当前金矿或不挖当前金矿)。
-
相同的颜色代表了方法被传入相同的参数
-
自底向上求解
w < p[n-1] : F(n,w)= F(n-1,W) (n≥1, w<p[n-1])
w ≥ p[n-1] : F(n,w) = max(F(n-1,w), F(n-1,w-p[n-1])+g[n-1])
例如:F(2,10) = max(F(2-1,10),F(2-1,10-5)+500) = max(F(1,10),F(1,5)+500) = max(400,400+500) = 900
n/w | 1个工人 | 2个工人 | 3个工人 | 4个工人 | 5个工人 | 6个工人 | 7个工人 | 8个工人 | 9个工人 | 10个工人 |
---|---|---|---|---|---|---|---|---|---|---|
400kg黄金/5人 | 0 | 0 | 0 | 0 | 400 | 400 | 400 | 400 | 400 | 400 |
500kg黄金/5人 | 0 | 0 | 0 | 0 | 500 | 500 | 500 | 500 | 500 | 900 |
200kg黄金/3人 | 0 | 0 | 200 | 200 | 500 | 500 | 500 | 700 | 700 | 900 |
300kg黄金/4人 | 0 | 0 | 200 | 300 | 500 | 500 | 500 | 700 | 800 | 900 |
350kg黄金/3人 | 0 | 0 | 350 | 350 | 500 | 550 | 650 | 850 | 850 | 900 |
- 代码实现:
package some_problem;
/**
* Copyright (C), 2019-2020
* author candy_chen
* date 2020/7/30 16:00
* version 1.0
* Description: 测试
*/
/**
*
*/
public class GetBestGoldMining {