矿工挖矿问题

假设某地区有5座钻石矿,每座钻石矿的钻石储量不同,根据挖矿难度,需要参与挖掘的工人数量也不同。假设能够参与挖矿工人的总数是10人,且每座钻石矿要么全挖,要么不挖,不能只派出一部分人挖取一部分矿产。要求用程序求解出,要想得到尽可能多的钻石,应该选择挖取哪几座矿产?

矿产编号钻石储量所需工人数量
14005
25005
32003
43004
53503

方案:
m个工人,设第n个矿所需的工人为L[n],能产钻石G[n]。在到达本矿需要人数前,产量等于前n-1各矿,F(n-1,m)
一,放弃第n个矿,产量为n-1个矿,F(n-1,m)
二,从m人中分出L[n]个人去处理第n个矿,产量为缺了L[n]个人的前n-1个矿的产量+第n个矿的产量,F(n-1,m-L[n])+G[n]
F(n,m)=F(n-1,m)  (n>1,m<L[n])
F(n,m)=max(F(n-1,m),F(n-1,m-L[n])+G[n])  (n>1,m>=L[n])

初始情况
矿产数量nm=1m=2m=3m=4m=5m=6m=7m=8m=9m=10
1
2
3
4
5

在挖掘第一个矿产时,由于其所需的工人数量为5,所以当m 的取值小于5时,根据公式F(n,m)=0(n≤1,m<L[0]),获得的钻石数量均为0。

当m 的取值大于或等于5时,根据公式F(n,m)=G[0](n==1,m≥L[0]),钻石数量的取值为400。

这样就确定了边界条件。

挖第一个矿
矿产数量nm=1m=2m=3m=4m=5m=6m=7m=8m=9m=10
10000400400400400400400
2
3
4
5

在挖掘第2个矿产时,由于其需要5个人进行挖掘,因此当m 取值小于5时,根据公式F(n,m)=F(n-1,m)(n>1,m<L[n-1]),F(2,m)=F(1,m)=0;当m 取值大于或等于5时,根据公式F(n,m)=max{F(n-1,m),F(n-1,m-L[n-1])+G[n-1]}(n>1,m≥L[n-1]),在5~9人的区间里,获得的钻石数量为500,即所有人都去参加第2个矿产的挖掘时获得的钻石量。

这是因为当m∈{5,9}时,F(1,m)<F(1,m-5)+500,但人数只够挖掘1个矿产,故选择储量较大的矿产。而在参与人数上升为10人时,上式仍成立,但此时两个矿产可以同时挖掘,因此获得的钻石数量为900。

挖第二个矿
矿产数量nm=1m=2m=3m=4m=5m=6m=7m=8m=9m=10
10000400400400400400400
20000500500500500500900
3
4
5

同理,在挖掘第3个矿产时,钻石产出量为200,需要的工人数量为3。

挖第三个矿
矿产数量nm=1m=2m=3m=4m=5m=6m=7m=8m=9m=10
10000400400400400400400
20000500500500500500900
300200200500500500700700900
4
5

第4个矿产的钻石产出量为300,需要的工人数量为4。

挖第四个矿
矿产数量nm=1m=2m=3m=4m=5m=6m=7m=8m=9m=10
10000400400400400400400
20000500500500500500900
300200200500500500700700900
400200300500500500700800900
5

针对第5个矿产的钻石产出量。

挖第五个矿
矿产数量nm=1m=2m=3m=4m=5m=6m=7m=8m=9m=10
10000400400400400400400
20000500500500500500900
300200200500500500700700900
400200300500500500700800900
500350350500550650850850900

根据以上思路,在用程序实现该算法的过程中,采用自底向上的方式进行计算,像填表过程一样从左至右、从上到下逐渐获得计算结果。这样,可以不需要存储整个表格的内容,仅需要存储前一行的结果,就可以推出下一行的内容,避免了重复计算。

代码:

def goldMine(n, m, g, L):
    t_results = [0 for _ in range(m + 1)]  # 保存上一行结果的数组
    for i in range(1, m + 1):  # 填充边界格子的值,从左向右填充表格第一行的内容
        if i < L[0]:  # 第一个矿
            t_results[i] = 0  # 若当前人数少于挖掘第一个金矿所需人数,黄金量为0
        else:
            t_results[i] = g[0]  # 若当前人数不少于第一个金矿所需人数,黄金量为g[0]
    for i in range(1, n):  # 外层循环为金矿数量
        results = [0 for _ in range(m + 1)]  # 保存返回结果的数组
        for j in range(1, m + 1):  # 内层循环为矿工数量
            if j < L[i]:  # 是否达到该矿所需人数
                results[j] = t_results[j]
            else:
                results[j] = max(t_results[j], t_results[j - L[i]] + g[i])
        t_results = results
    return t_results[-1]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

algorithm6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值