这是看到一位大神,写的关于dynamic programming的博客,认为很好。简单分析下。然后给出链接。
背景问题就是
有一个国家,全部的国民都很老实憨厚,某天他们在自己的国家发现了十座金矿。而且这十座金矿在地图上排成一条直线,国王知道这个消息后很高兴。他希望可以把这些金子都挖出来造福国民,首先他把这些金矿依照在地图上的位置从西至东进行编号,依次为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个人的情况下最多能挖出多少金子呢?国王是怎样思考这个问题的呢?
为了更好让自己理解这个问题
先考虑比較简单的三座山的情况
从问题的最后一步入手。就是在要开採第三座金矿时, 假设如今有总人数 n人。处理函数为f(可用人数,开採前m座金矿)。返回数目为前m座金矿的最大可採到的金子。
初始化这些数据
总人数75个人。75<80。没有能力全部开採金矿,第一次 前3座金矿时
f(75,3)须要考虑的问题:
1)人数是不是大于开採需求 2)是不是已经到最后一个用伪代码表示为:
if(是最后一个金矿){ if(人数够开採金矿) return 金矿金子 else return 0。}else //不是最后一个金矿{ if(人数够开採) { 比較 本座金矿金子+f(前n-1座金矿)和 f(前n-1座金矿); return 最大的 } else //不够开採本座 { return f(前n-1座金矿); }}
所以
f(75,3){ return max(f(75,2),f(25,2)+300);}f(75,2){ return max(f(75,1),f(55,1)+110);}f(25,2){ return max(f(25,1),f(5,1)+110);}f(75,1){ return 100;}f(55,1){ return 100;}f(25,1){ return 100;}f(5,1){ return 0;}
更形象的图为
大神博客链接