经过金矿模型介绍动态规划

做者:贵州大学 05级 刘永辉 因为帖子太长 分三次发 这是第一部分 对于动态规划,每一个刚接触的人都须要一段时间来理解,特别是第一次接触的时候老是想不通为何这种方法可行,这篇文章就是为了帮助你们理解动态规划,并经过讲解基本的01背包问题来引导读者如何去思考动态规划。本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,因此若是你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你可贵读懂的地方,请跟贴指出,谢谢! ----第一节----初识动态规划--------       经典的01背包问题是这样的:       有一个包和n个物品,包的容量为m,每一个物品都有各自的体积和价值,问当从这n个物品中选择多个物品放在包里而物品体积总数不超过包的容量m时,可以获得的最大价值是多少?[对于每一个物品不能够取屡次,最多只能取一次,之因此叫作01背包,0表示不取,1表示取]       为了用一种生动又更形象的方式来说解此题,我把此题用另外一种方式来描述,以下:             有一个国家,全部的国民都很是老实憨厚,某天他们在本身的国家发现了十座金矿,而且这十座金矿在地图上排成一条直线,国王知道这个消息后很是高兴,他但愿可以把这些金子都挖出来造福国民,首先他把这些金矿按照在地图上的位置从西至东进行编号,依次为0、一、二、三、四、五、六、七、八、9,而后他命令他的手下去对每一座金矿进行勘测,以便知道挖取每一座金矿须要多少人力以及每座金矿可以挖出多少金子,而后动员国民都来挖金子。       题目补充1:挖每一座金矿须要的人数是固定的,多一我的少一我的都不行。国王知道每一个金矿各须要多少人手,金矿i须要的人数为peopleNeeded[i]。       题目补充2:每一座金矿所挖出来的金子数是固定的,当第i座金矿有peopleNeeded[i]人去挖的话,就必定能刚好挖出gold[i]个金子。不然一个金子都挖不出来。       题目补充3:开采一座金矿的人完成开采工做后,他们不会再次去开采其它金矿,所以一我的最多只能使用一次。       题目补充4:国王在全国范围内仅招募到了10000名愿意为了国家去挖金子的人,所以这些人可能不够把全部的金子都挖出来,可是国王但愿挖到的金子越多越好。       题目补充5:这个国家的每个人都很老实(包括国王),不会私吞任何金子,也不会弄虚做假,不会说谎言。       题目补充6:有不少人拿到这个题后的第一反应就是对每个金矿求出平均每一个人能挖出多少金子,而后从高到低进行选择,这里要强调这种方法是错的,若是你也是这样想的,请考虑背包模型,当有一个背包的容量为10,共有3个物品,体积分别是三、三、5,价值分别是六、六、9,那么你的方法取到的是前两个物品,总价值是12,但明显最大值是后两个物品组成的15。       题目补充7:咱们只须要知道最多能够挖出多少金子便可,而不用关心哪些金矿挖哪些金矿不挖。       那么,国王究竟如何知道在只有10000我的的状况下最多能挖出多少金子呢?国王是如何思考这个问题的呢?       国王首先来到了第9个金矿的所在地(注意,第9个就是最后一个,由于是从0开始编号的,最西边的那个金矿是第0个),他的臣子告诉他,若是要挖取第9个金矿的话就须要1500我的,而且第9个金矿能够挖出8888个金子。听到这里国王哈哈大笑起来,由于原先他觉得要知道十个金矿在仅有10000我的的状况下最多能挖出多少金子是一件很难思考的问题,可是,就在刚才听完他的臣子所说的那句话时,国王已经知道总共最多能挖出多少金子了,国王是如何在不了解其它金矿的状况下知道最多能挖出多少金子的呢?他的臣子们也不知道这个谜,所以他的臣子们就问他了:“最聪明的国王陛下,咱们都没有告诉您其它金矿的状况,您是如何知道最终答案的呢?”       得意的国王笑了笑,而后把他最得意的“左、右手”叫到跟前,说到:“我并不须要考虑最终要挖哪些金矿才能获得最多的金子,我只须要考虑我面前的这座金矿就能够了,对于我面前的这座金矿不外乎仅有两种选择,要么挖,要么不挖,对吧?”       “固然,固然”大臣们回答倒。             国王继续说道:“若是我挖取第9座金矿的话那么我如今就能得到8888个金子,而我将用去1500我的,那么我还剩下8500我的。我亲爱的左部下,若是你告诉我当我把全部剩下的8500我的和全部剩下的其它金矿都交给你去开采你最多能给我挖出多少金子的话,那么我不就知道了在第9个金矿必定开采的状况下所能获得的最大金币数吗?”             国王的左部下听后回答道:“国王陛下,您的意思是若是我能用8500我的在其它金矿最多开采出x个金币的话,那您一共就可以得到 x + 8888个金子,对吗?”             “是啊,是啊……若是第9座金矿必定开采的话……”大臣们点头说到。             国王笑着继续对着他的右部下说到:“亲爱的右部下,也许我并不打算开采这第9座金矿,那么我依然拥有10000我的,若是我把这10000我的和剩下的金矿都给你的话,你最多能给我挖出多少个金子呢?”             国王的右部下聪明地说道:“尊敬的国王陛下,我明白您的意思了,若是我回答最多能购开采出y个金币的话,那您就能够在y和x+8888之间选择一个较大者,而这个较大者就是最终咱们能得到的最大金币数,您看我这样理解对吗?”             国王笑得更灿烂了,问他的左部下:“那么亲爱的左部下,我给你8500我的和其他金矿的话你能告诉我最多能挖出多少金子吗?”       “请您放心,这个问题难不倒我”。左部下向国王打包票说到。       国王高兴地继续问他的右部下:“那右部下你呢,若是我给你10000我的和其他金矿的话你能告诉我最多能挖出多少金子吗?”       “固然能了!交给我吧!”右部下同左部下同样自信地回答道。       “那就拜托给大家两位了,如今我要回到我那温馨的王宫里去享受了,我期待着大家的答复。”国王说完就开始动身回去等消息了,他是多么地相信他的两个大臣可以给他一个准确的答复,由于国王其实知道他的两位大臣要比他聪明得多。       故事发展到这里,你是否在想国王的这两个大臣又是如何找到让国王满意的答案的呢?他们为何可以如此自信呢?事实上他们的确比国王要聪明一些,由于他们从国王的身上学到了一点,就是这一点让他们充满了自信。       国王走后,国王的左、右部下来到了第8座金矿,早已在那里等待他们的金矿勘测兵向两位大臣报道:“聪明的两位大臣,您们好,第8座金矿须要1000我的才能开采,能够得到7000个金子”。       由于国王仅给他的左部下8500我的,因此国王的左部下叫来了两我的,对着其中一我的问到:“若是我给你7500我的和除了第八、第9的其它全部金矿的话,你能告诉我你最多能挖出多少金子吗?”       而后国王的左部下继续问另外一我的:“若是我给你8500我的和除了第八、第9的其它全部金矿的话,你能告诉我你最多能挖出多少金子吗?”       国王的左部下在内心想着:“若是他们俩都能回答个人问题的话,那国王交给个人问题不就解决了吗?哈哈哈!”       由于国王给了他的右部下10000我的,因此国王的右部下一样也叫来了两我的,对着其中一我的问:“若是我给你9000我的和除了第八、第9的其它全部金矿的话,你能告诉我你最多能挖出多少金子吗?”       而后国王的右部下继续问他叫来的另外一我的:“若是我给你10000我的和除了第八、第9的其它全部金矿的话,你能告诉我你最多能挖出多少金子吗?”       此时,国王的右部下同左部下同样,他们都在为本身如此聪明而感到知足。             固然,这四个被叫来的人一样自信地回答没有问题,由于他们一样地从这两个大臣身上学到了相同的一点,而两位自认为本身同样很聪明的大臣得意地笑着回到了他们的府邸,等着别人回答他们提出来的问题,如今你知道了这两个大臣是如何解决国王交待给他们的问题了吗?       那么你认为被大臣叫去的那四我的又是怎么完成大臣交给他们的问题的呢?答案固然是他们找到了另外八我的!       没用多少功夫,这个问题已经在全国传开了,更多人的人找到了更更多的人来解决这个问题,而有些人却不须要去另外找两我的帮他,哪些人不须要别人的帮助就能够回答他们的问题呢?       很明显,当被问到给你z我的和仅有第0座金矿时最多能挖出多少金子时,就不须要别人的帮助,由于你知道,若是z大于等于挖取第0座金矿所须要的人数的话,那么挖出来的最多金子数就是第0座金矿可以挖出来的金子数,若是这z我的不够开采第0座金矿,那么能挖出来的最多金子数就是0,由于这惟一的金矿不够人力去开采。让咱们为这些不须要别人的帮助就能够准确地得出答案的人们鼓掌吧,这就是传说中的底层劳动人民!       故事讲到这里先暂停一下,咱们如今从新来分析一下这个故事,让咱们对动态规划有个理性认识。       子问题:       国王须要根据两个大臣的答案以及第9座金矿的信息才能判断出最多可以开采出多少金子。为了解决本身面临的问题,他须要给别人制造另外两个问题,这两个问题就是子问题。       思考动态规划的第一点----最优子结构:       国王相信,只要他的两个大臣可以回答出正确的答案(对于考虑可以开采出的金子数,最多的也就是最优的同时也就是正确的),再加上他的聪明的判断就必定能获得最终的正确答案。咱们把这种子问题最优时母问题经过优化选择后必定最优的状况叫作“最优子结构”。       思考动态规划的第二点----子问题重叠:       实际上国王也好,大臣也好,全部人面对的都是一样的问题,即给你必定数量的人,给你必定数量的金矿,让你求出可以开采出来的最多金子数。咱们把这种母问题与子问题本质上是同一个问题的状况称为“子问题重叠”。然而问题中出现的不一样点每每就是被子问题之间传递的参数,好比这里的人数和金矿数。             思考动态规划的第三点----边界:       想一想若是不存在前面咱们提到的那些底层劳动者的话这个问题能解决吗?永远都不可能!咱们把这种子问题在必定时候就再也不须要提出子子问题的状况叫作边界,没有边界就会出现死循环。       思考动态规划的第四点----子问题独立:       要知道,当国王的两个大臣在思考他们本身的问题时他们是不会关心对方是如何计算怎样开采金矿的,由于他们知道,国王只会选择两我的中的一个做为最后方案,另外一我的的方案并不会获得实施,所以一我的的决定对另外一我的的决定是没有影响的。咱们把这种一个母问题在对子问题选择时,当前被选择的子问题两两互不影响的状况叫作“子问题独立”。       这就是动态规划,具备“最优子结构”、“子问题重叠”、“边界”和“子问题独立”,当你发现你正在思考的问题具有这四个性质的话,那么恭喜你,你基本上已经找到了动态规划的方法。       有了上面的这几点,咱们就能够写出动态规划的转移方程式,如今咱们来写出对应这个问题的方程式,若是用gold[mineNum]表示第mineNum个金矿可以挖出的金子数,用peopleNeeded[mineNum]表示挖第mineNum个金矿须要的人数,用函数f(people,mineNum)表示当有people我的和编号为0、一、二、三、……、mineNum的金矿时可以获得的最大金子数的话,f(people,mineNum)等于什么呢?或者说f(people,mineNum)的转移方程是怎样的呢?       答案是: 当mineNum = 0且people >= peopleNeeded[mineNum]时 f(people,mineNum) = gold[mineNum]       当mineNum = 0且people < peopleNeeded[mineNum]时 f(people,mineNum) = 0       当mineNum != 0时 f(people,mineNum) = f(people-peopleNeeded[mineNum], mineNum-1) + gold[mineNum]与f(people, mineNum-1)中的较大者,前两个式子对应动态规划的“边界”,后一个式子对应动态规划的“最优子结构”请读者弄明白后再继续往下看。 这是第二部分 ----第二节----动态规划的优势--------             如今我假设读者你已经搞清楚了为何动态规划是正确的方法,可是咱们为何须要使用动态规划呢?请先继续欣赏这个故事:       国王得知他的两个手下使用了和他相同的方法去解决交代给他们的问题后,不但没有认为他的两个大臣在偷懒,反而很高兴,由于他知道,他的大臣必然会找更多的人一块儿解决这个问题,而更多的人会找更更多的人,这样他这个聪明的方法就会在不经意间流传开来,而全国人民都会知道这个聪明的方法是他们伟大的国王想出来的,你说国王能不高兴吗?       可是国王也有一些担心,由于他实在不知道这个“工程”要动用到多少人来完成,若是帮助他解决这个问题的人太多的话那么就太劳民伤财了。“会不会影响到今年的收成呢?”国王在内心想着这个问题,因而他请来了整个国家里惟一的两个数学天才,一个叫作小天,另外一个叫作小才。       国王问小天:“小天啊,我发觉这个问题有点严重,我知道其实这能够简单的当作一个组合问题,也就是从十个金矿中选取若干个金矿进行开采,看看哪一种组合获得的金子最多,也许用组合方法会更好一些。你能告诉我一共有多少种组合状况吗?”       “国王陛下,若是用组合方法的话一共要考虑2的10次方种状况,也就是1024种状况。”小天思考了一会回答到。       “嗯……,若是每一种状况我交给一我的去计算能获得的金子数的话,那我也要1024我的,其实仍是挺多的。”国王好像再次感受到了本身的方法是正确的。       国王心理期待着小才可以给它一个更好的答案,问到:“小才啊,那么你能告诉我用个人那个方法总共须要多少人吗?其实,我也计算过,好像须要的人数是1+2+4+8+16+32+64+……,毕竟每个人的确都须要找另外两我的来帮助他们……”       不辜负国王的期待,小才微笑着说到:“亲爱的国王陛下,其实咱们并不须要那么多人,由于有不少问题实际上是相同的,而咱们只须要为每个不一样的问题使用一我的力即可。”       国王高兴的问到:“此话如何讲?”       “打个比方,若是有一我的须要知道1000我的和3个金矿能够开采出多少金子,同时另外一我的也须要知道1000我的和3个金矿能够开采出多少金子的话,那么他们能够去询问相同的一我的,而不用各自找不一样的人浪费人力了。”             国王思考着说到:“嗯,颇有道理,若是问题是同样的话那么就不须要去询问两个不一样的人了,也就是说一个不一样的问题仅须要一我的力,那么一共有多少个不一样的问题呢?”          “由于每一个问题的人数能够从0取到10000,而金矿数能够从0取到10,因此最多大约有10000 * 10 等于100000个不一样的问题。” 小才一边算着一边回答。       “什么?十万个问题?十万我的力?”国王有点失望。       “请国王放心,事实上咱们须要的人力远远小于这个数的,由于不是每个问题都会遇到,也许咱们仅须要1、两百我的力就能够解决这个问题了,这主要和各个金矿所须要的人数有关。” 小才马上回答到。       故事的最后,天然是国王再一次向他的臣民们证实了他是这个国家里最聪明的人,如今咱们经过故事的第二部分来考虑动态规划的另外两个思考点。       思考动态规划的第五点----作备忘录:       正如上面所说的同样,当咱们遇到相同的问题时,咱们能够问同一我的。讲的通俗一点就是,咱们能够把问题的解放在一个变量中,若是再次遇到这个问题就直接从变量中得到答案,所以每个问题仅会计算一遍,若是不作备忘的话,动态规划就没有任何优点可言了。                    思考动态规划的第六点----时间分析:       正如上面所说,若是咱们用穷举的方法,至少须要2^n个常数时间,由于总共有2^n种状况须要考虑,若是在背包问题中,包的容量为1000,物品数为100,那么须要考虑2^100种状况,这个数大约为10的30次方。       而若是用动态规划,最多大概只有1000*100 = 100000个不一样的问题,这和10的30次方比起来优点是很明显的。而实际状况并不会出现那么多不一样的问题,好比在金矿模型中,若是全部的金矿所需人口都是1000我的,那么问题总数大约只有100个。       非正式地,咱们能够很容易获得动态规划所需时间,若是共有questionCount个相同的子问题,而每个问题须要面对chooseCount种选择时,咱们所需时间就为questionCount * chooseCount个常数。在金矿模型中,子问题最多有大概people * n 个(其中people是用于开采金矿的总人数,n是金矿的总数),所以questionCount = people * n,而就像国王须要考虑是采用左部下的结果仍是采用右部下的结果同样,每一个问题面对两个选择,所以chooseCount = 2,因此程序运行时间为 T = O(questionCount * chooseCount) =O(people * n),别忘了实际上须要的时间小于这个值,根据所遇到的具体状况有所不一样。       这就是动态规划的魔力,它减小了大量的计算,所以咱们须要动态规划!                           ----第三节----动态规划的思考角度----------             那么什么是动态规划呢?我我的以为,若是一个解决问题的方法知足上面六个思考点中的前四个,那么这个方法就属于动态规划。而在思考动态规划方法时,后两点一样也是须要考虑的。       面对问题要寻找动态规划的方法,首先要清楚一点,动态规划不是算法,它是一种方法,它是在一件事情发生的过程当中寻找最优值的方法,所以,咱们须要对这件事情所发生的过程进行考虑。而一般咱们从过程的最后一步开始考虑,而不是先考虑过程的开始。       打个比方,上面的挖金矿问题,咱们能够认为整个开采过程是从西至东进行开采的(也就是从第0座开始),那么总有面对最后一座金矿的时候(第9座),对这座金矿不外乎两个选择,开采与不开采,在最后一步肯定时再去肯定倒数第二步,直到考虑第0座金矿(过程的开始)。       而过程的开始,也就是考虑的最后一步,就是边界。       所以在遇到一个问题想用动态规划的方法去解决时,不妨先思考一下这个过程是怎样的,而后考虑过程的最后一步是如何选择的,一般咱们须要本身去构造一个过程,好比后面的练习。 ----第四节----总结-------       那么遇到问题如何用动态规划去解决呢?根据上面的分析咱们能够按照下面的步骤去考虑:       一、构造问题所对应的过程。       二、思考过程的最后一个步骤,看看有哪些选择状况。       三、找到最后一步的子问题,确保符合“子问题重叠”,把子问题中不相同的地方设置为参数。       四、使得子问题符合“最优子结构”。       五、找到边界,考虑边界的各类处理方式。       六、确保知足“子问题独立”,通常而言,若是咱们是在多个子问题中选择一个做为实施方案,而不会同时实施多个方案,那么子问题就是独立的。       七、考虑如何作备忘录。       八、分析所需时间是否知足要求。       九、写出转移方程式。       ----第五节----练习-------       题目一:买书       有一书店引进了一套书,共有3卷,每卷书订价是60元,书店为了搞促销,推出一个活动,活动以下:             若是单独购买其中一卷,那么能够打9.5折。       若是同时购买两卷不一样的,那么能够打9折。       若是同时购买三卷不一样的,那么能够打8.5折。             若是小明但愿购买第1卷x本,第2卷y本,第3卷z本,那么至少须要多少钱呢?(x、y、z为三个已知整数)。       固然,这道题彻底能够不用动态规划来解,可是如今咱们是要学习动态规划,所以请想一想如何用动态规划来作?       答案:       一、过程为一次一次的购买,每一次购买也许只买一本(这有三种方案),或者买两本(这也有三种方案),或者三本一块儿买(这有一种方案),最后直到买完全部须要的书。       二、最后一步我必然会在7种购买方案中选择一种,所以我要在7种购买方案中选择一个最佳状况。       三、子问题是,我选择了某个方案后,如何使得购买剩余的书能用最少的钱?而且这个选择不会使得剩余的书为负数。母问题和子问题都是给定三卷书的购买量,求最少须要用的钱,因此有“子问题重叠”,问题中三个购买量设置为参数,分别为i、j、k。       四、的确符合。       五、边界是一次购买就能够买完全部的书,处理方式请读者本身考虑。       六、每次选择最多有7种方案,而且不会同时实施其中多种,所以方案的选择互不影响,因此有“子问题独立”。       七、我能够用minMoney[i][j][k]来保存购买第1卷i本,第2卷j本,第3卷k本时所需的最少金钱。       八、共有x * y * z 个问题,每一个问题面对7种选择,时间为:O( x * y * z * 7) =  O( x * y * z )。       九、用函数MinMoney(i,j,k)来表示购买第1卷i本,第2卷j本,第3卷k本时所需的最少金钱,那么有:               MinMoney(i,j,k)=min(s1,s2,s3,s4,s5,s6,s7),其中s1,s2,s3,s4,s5,s6,s7分别为对应的7种方案使用的最少金钱:               s1 = 60 * 0.95 + MinMoney(i-1,j,k)               s2 = 60 * 0.95 + MinMoney(i,j-1,k)               s3 = 60 * 0.95 + MinMoney(i,j,k-1)               s4 = (60 + 60) * 0.9 + MinMoney(i-1,j-1,k)               s5 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1)               s6 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1)               s7 = (60 + 60 + 60) * 0.85 + MinMoney(i-1,j-1,k-1) 这是第三部分 ----第六节----代码参考------       下面提供金矿问题的程序源代码帮助读者理解,并提供测试数据给你们练习。       输入文件名为“beibao.in”,由于这个问题实际上就是背包问题,因此测试数据文件名就保留原名吧。       输入文件第一行有两个数,第一个是国王可用用来开采金矿的总人数,第二个是总共发现的金矿数。       输入文件的第2至n+1行每行有两个数,第i行的两个数分别表示第i-1个金矿须要的人数和能够获得的金子数。       输出文件仅一个整数,表示可以获得的最大金子数。       输入样例:       100 5       77 92       22 22       29 87       50 46       99 90       输出样例:       133             参考代码以下:   /* =========程序信息======== 对应题目:01背包之金矿模型 使用语言:c++ 使用编译器:Visual Studio 2005.NET 使用算法:动态规划 算法运行时间:O(people * n) [people是人数,n是金矿数] 做者:贵州大学05级 刘永辉 昵称:SDJL 编写时间:2008年8月 联系QQ:44561907 E-Mail:44561907@qq.com 得到更多文章请访问个人博客:www.cnblogs.com/sdjl 若是发现BUG或有写得很差的地方请发邮件告诉我:) 转载请保留此部分信息:) */ #include "stdafx.h" #include <iostream> #include <fstream> using namespace std; const int max_n = 100;//程序支持的最多金矿数 const int max_people = 10000;//程序支持的最多人数 int n;//金矿数 int peopleTotal;//能够用于挖金子的人数 int peopleNeed[max_n];//每座金矿须要的人数 int gold[max_n];//每座金矿可以挖出来的金子数 int maxGold[max_people][max_n];//maxGold[i][j]保存了i我的挖前j个金矿可以获得的最大金子数,等于-1时表示未知 //初始化数据 void init() {     ifstream inputFile("beibao.in");     inputFile>>peopleTotal>>n;     for(int i=0; i <n; i++)         inputFile>>peopleNeed[i]>>gold[i];     inputFile.close();                 for(int i=0; i <=peopleTotal; i++)         for(int j=0; j <n; j++)             maxGold[i][j] = -1;//等于-1时表示未知 [对应动态规划中的“作备忘录”]         } //得到在仅有people我的和前mineNum个金矿时可以获得的最大金子数,注意“前多少个”也是从0开始编号的 int GetMaxGold(int people, int mineNum) {     //申明返回的最大金子数     int retMaxGold;     //若是这个问题曾经计算过  [对应动态规划中的“作备忘录”]     if(maxGold[people][mineNum] != -1)     {         //得到保存起来的值         retMaxGold = maxGold[people][mineNum];     }     else if(mineNum == 0)//若是仅有一个金矿时 [对应动态规划中的“边界”]     {         //当给出的人数足够开采这座金矿         if(people >= peopleNeed[mineNum])         {                //获得的最大值就是这座金矿的金子数             retMaxGold = gold[mineNum];         }         else//不然这惟一的一座金矿也不能开采         {             //获得的最大值为0个金子             retMaxGold = 0;         }     }     else if(people >= peopleNeed[mineNum])//若是给出的人够开采这座金矿 [对应动态规划中的“最优子结构”]     {         //考虑开采与不开采两种状况,取最大值         retMaxGold = max(GetMaxGold(people - peopleNeed[mineNum],mineNum -1) + gold[mineNum],                                         GetMaxGold(people,mineNum - 1));     }     else//不然给出的人不够开采这座金矿 [对应动态规划中的“最优子结构”]     {         //仅考虑不开采的状况         retMaxGold  = GetMaxGold(people,mineNum - 1);     }         //作备忘录        maxGold[people][mineNum] = retMaxGold;     return retMaxGold; } int _tmain(int argc, _TCHAR* argv[]) {     //初始化数据     init();     //输出给定peopleTotal我的和n个金矿可以得到的最大金子数,再次提醒编号从0开始,因此最后一个金矿编号为n-1     cout < <GetMaxGold(peopleTotal,n-1);     system("pause");     return 0; }