本文主要总结了引文中提出的金矿模型的思考方法,并用python代码来实现算法,从而加深了对动态规划思想的理解。
1. 故事描述
注:内容节选自开篇引文。
有一个国家,所有的国民都非常老实憨厚,某天他们在自己的国家发现了十座金矿,并且这十座金矿在地图上排成一条直线,国王知道这个消息后非常高兴,他希望能够把这些金子都挖出来造福国民,首先他把这些金矿按照在地图上的位置从西至东进行编号,依次为0、1、2、3、4、5、6、7、8、9,然后他命令他的手下去对每一座金矿进行勘测,以便知道挖取每一座金矿需要多少人力以及每座金矿能够挖出多少金子,然后动员国民都来挖金子。
- 题目补充1:挖每一座金矿需要的人数是固定的,多一个人少一个人都不行。国王知道每个金矿各需要多少人手,金矿i需要的人数为peopleNeeded[i]。
- 题目补充2:每一座金矿所挖出来的金子数是固定的,当第i座金矿有peopleNeeded[i]人去挖的话,就一定能恰好挖出gold[i]个金子。否则一个金子都挖不出来。
- 题目补充3:开采一座金矿的人完成开采工作后,他们不会再次去开采其它金矿,因此一个人最多只能使用一次。
- 题目补充4:国王在全国范围内仅招募到了10000名愿意为了国家去挖金子的人,因此这些人可能不够把所有的金子都挖出来,但是国王希望挖到的金子越多越好。
- 题目补充5:这个国家的每一个人都很老实(包括国王),不会私吞任何金子,也不会弄虚作假,不会说谎话。
- 题目补充6:有很多人拿到这个题后的第一反应就是对每一个金矿求出平均每个人能挖出多少金子,然后从高到低进行选择,这里要强调这种方法是错的,如果你也是这样想的,请考虑背包模型,当有一个背包的容量为10,共有3个物品,体积分别是3、3、5,价值分别是6、6、9,那么你的方法取到的是前两个物品,总价值是12,但明显最大值是后两个物品组成的15。
- 题目补充7:我们只需要知道最多可以挖出多少金子即可,而不用关心哪些金矿挖哪些金矿不挖。
那么,国王究竟如何知道在只有10000个人的情况下最多能挖出多少金子呢?
2. 问题抽象
注:内容节选自开篇引文。
输入文件名为“gold.in”。
输入文件第一行有两个数M和N,M是国王可用用来开采金矿的总人数,N是总共发现的金矿数。
输入文件的第2至N+1行每行有两个数,第i行的两个数分别表示第i-1个金矿需要的人数和可以得到的金子数。
输出文件仅一个整数,表示能够得到的最大金子数。
输入样例:
100 5
77 92
22 22
29 87
50 46
99 90
输出样例:
133
3. 分析
按照原博客中的思路进行分析,定义如下几个数组和函数:
- needed_people_num[i]:表示开采金矿i(注意:i从0开始,0 <= i < N,下同)所需的人数。
- gold_num[i]:表示开采金矿i能获取到的金子数。
- f(people_num,mine_num):表示当用people_num个人挖第0~mine_num座金矿可以获取到的最大金子数。
状态转移方程如下:
注:其中将people_num简记为:pn,mine_num简记为:mn,needed_people_num[]简记为:npn[],gold_num简记为:gn