动态规划入门详解

高速内部总线HSIB和设备总线DB 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 前言 “纸上谈兵”已经快一年,这项目有点意思了,其实、有难度的事情才好玩。从年初至今陆续买了20多套各类开发板,我还没一套去上手试玩;只是买回来“摸摸”感受一下,看看相关资料、用“想象力”探视和思考,之后就丢弃一旁“吃灰”了。音响成品倒是试用过不少,那又不用“开发”,只是用 心去“试听”和比较吧。“飞鸡2号和飞鸡1号”合 阅读详情

         对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划。本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读懂的地方,请跟贴指出,谢谢!

 

 

 

 

----第一节----初识动态规划--------

 

       经典的01背包问题是这样的:

       有一个包和n个物品,包的容量为m,每个物品都有各自的体积和价值,问当从这n个物品中选择多个物品放在包里而物品体积总数不超过包的容量m时,能够得到的最大价值是多少?[对于每个物品不可以取多次,最多只能取一次,之所以叫做01背包,0表示不取,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个人的情况下最多能挖出多少金子呢?国王是如何思考这个问题的呢?

 

       国王首先来到了第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个人和除了第8、第9的其它所有金矿的话,你能告诉我你最多能挖出多少金子吗?”

 

       然后国王的左部下继续问另一个人:“如果我给你8500个人和除了第8、第9的其它所有金矿的话,你能告诉我你最多能挖出多少金子吗?”

 

       国王的左部下在心里想着:“如果他们俩都能回答我的问题的话,那国王交给我的问题不就解决了吗?哈哈哈!”

 

       因为国王给了他的右部下10000个人,所以国王的右部下同样也叫来了两个人,对着其中一个人问:“如果我给你9000个人和除了第8、第9的其它所有金矿的话,你能告诉我你最多能挖出多少金子吗?”

 

       然后国王的右部下继续问他叫来的另一个人:“如果我给你10000个人和除了第8、第9的其它所有金矿的话,你能告诉我你最多能挖出多少金子吗?”

 

       此时,国王的右部下同左部下一样,他们都在为自己如此聪明而感到满足。

      

       当然,这四个被叫来的人同样自信地回答没有问题,因为他们同样地从这两个大臣身上学到了相同的一点,而两位自认为自己一样很聪明的大臣得意地笑着回到了他们的府邸,等着别人回答他们提出来的问题,现在你知道了这两个大臣是如何解决国王交待给他们的问题了吗?

 

       那么你认为被大臣叫去的那四个人又是怎么完成大臣交给他们的问题的呢?答案当然是他们找到了另外八个人!

 

       没用多少功夫,这个问题已经在全国传开了,更多人的人找到了更更多的人来解决这个问题,而有些人却不需要去另外找两个人帮他,哪些人不需要别人的帮助就可以回答他们的问题呢?

 

       很明显,当被问到给你z个人和仅有第0座金矿时最多能挖出多少金子时,就不需要别人的帮助,因为你知道,如果z大于等于挖取第0座金矿所需要的人数的话,那么挖出来的最多金子数就是第0座金矿能够挖出来的金子数,如果这z个人不够开采第0座金矿,那么能挖出来的最多金子数就是0,因为这唯一的金矿不够人力去开采。让我们为这些不需要别人的帮助就可以准确地得出答案的人们鼓掌吧,这就是传说中的底层劳动人民!

 

       故事讲到这里先暂停一下,我们现在重新来分析一下这个故事,让我们对动态规划有个理性认识。

 

       子问题:

       国王需要根据两个大臣的答案以及第9座金矿的信息才能判断出最多能够开采出多少金子。为了解决自己面临的问题,他需要给别人制造另外两个问题,这两个问题就是子问题。

 

       思考动态规划的第一点----最优子结构:

       国王相信,只要他的两个大臣能够回答出正确的答案(对于考虑能够开采出的金子数,最多的也就是最优的同时也就是正确的),再加上他的聪明的判断就一定能得到最终的正确答案。我们把这种子问题最优时母问题通过优化选择后一定最优的情况叫做“最优子结构”。

 

       思考动态规划的第二点----子问题重叠:

       实际上国王也好,大臣也好,所有人面对的都是同样的问题,即给你一定数量的人,给你一定数量的金矿,让你求出能够开采出来的最多金子数。我们把这种母问题与子问题本质上是同一个问题的情况称为“子问题重叠”。然而问题中出现的不同点往往就是被子问题之间传递的参数,比如这里的人数和金矿数。

      

       思考动态规划的第三点----边界:

       想想如果不存在前面我们提到的那些底层劳动者的话这个问题能解决吗?永远都不可能!我们把这种子问题在一定时候就不再需要提出子子问题的情况叫做边界,没有边界就会出现死循环。

 

       思考动态规划的第四点----子问题独立:

       要知道,当国王的两个大臣在思考他们自己的问题时他们是不会关心对方是如何计算怎样开采金矿的,因为他们知道,国王只会选择两个人中的一个作为最后方案,另一个人的方案并不会得到实施,因此一个人的决定对另一个人的决定是没有影响的。我们把这种一个母问题在对子问题选择时,当前被选择的子问题两两互不影响的情况叫做“子问题独立”。

 

 

       这就是动态规划,具有“最优子结构”、“子问题重叠”、“边界”和“子问题独立”,当你发现你正在思考的问题具备这四个性质的话,那么恭喜你,你基本上已经找到了动态规划的方法。

 

       有了上面的这几点,我们就可以写出动态规划的转移方程式,现在我们来写出对应这个问题的方程式,如果用gold[mineNum]表示第mineNum个金矿能够挖出的金子数,用peopleNeeded[mineNum]表示挖第mineNum个金矿需要的人数,用函数f(people,mineNum)表示当有people个人和编号为0、1、2、3、……、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个不同的问题。” 小才一边算着一边回答。

 

       “什么?十万个问题?十万个人力?”国王有点失望。

 

       “请国王放心,事实上我们需要的人力远远小于这个数的,因为不是每一个问题都会遇到,也许我们仅需要一、两百个人力就可以解决这个问题了,这主要和各个金矿所需要的人数有关。” 小才立刻回答到。

 

       故事的最后,自然是国王再一次向他的臣民们证明了他是这个国家里最聪明的人,现在我们通过故事的第二部分来考虑动态规划的另外两个思考点。

 

       思考动态规划的第五点----做备忘录:

       正如上面所说的一样,当我们遇到相同的问题时,我们可以问同一个人。讲的通俗一点就是,我们可以把问题的解放在一个变量中,如果再次遇到这个问题就直接从变量中获得答案,因此每一个问题仅会计算一遍,如果不做备忘的话,动态规划就没有任何优势可言了。             

 

       思考动态规划的第六点----时间分析:

       正如上面所说,如果我们用穷举的方法,至少需要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座金矿(过程的开始)。

 

       而过程的开始,也就是考虑的最后一步,就是边界。

 

       因此在遇到一个问题想用动态规划的方法去解决时,不妨先思考一下这个过程是怎样的,然后考虑过程的最后一步是如何选择的,通常我们需要自己去构造一个过程,比如后面的练习。

 

 

 

 

 

 

 

----第四节----总结-------

 

       那么遇到问题如何用动态规划去解决呢?根据上面的分析我们可以按照下面的步骤去考虑:

 

       1、构造问题所对应的过程。

       2、思考过程的最后一个步骤,看看有哪些选择情况。

       3、找到最后一步的子问题,确保符合“子问题重叠”,把子问题中不相同的地方设置为参数。

       4、使得子问题符合“最优子结构”。

       5、找到边界,考虑边界的各种处理方式。

       6、确保满足“子问题独立”,一般而言,如果我们是在多个子问题中选择一个作为实施方案,而不会同时实施多个方案,那么子问题就是独立的。

       7、考虑如何做备忘录。

       8、分析所需时间是否满足要求。

       9、写出转移方程式。

      

 

 

 

 

----第五节----练习-------

 

       题目一:买书

       有一书店引进了一套书,共有3卷,每卷书定价是60元,书店为了搞促销,推出一个活动,活动如下:

      

       如果单独购买其中一卷,那么可以打9.5折。

       如果同时购买两卷不同的,那么可以打9折。

       如果同时购买三卷不同的,那么可以打8.5折。

      

       如果小明希望购买第1卷x本,第2卷y本,第3卷z本,那么至少需要多少钱呢?(x、y、z为三个已知整数)。

 

       当然,这道题完全可以不用动态规划来解,但是现在我们是要学习动态规划,因此请想想如何用动态规划来做?

 

       答案:

 

       1、过程为一次一次的购买,每一次购买也许只买一本(这有三种方案),或者买两本(这也有三种方案),或者三本一起买(这有一种方案),最后直到买完所有需要的书。

       2、最后一步我必然会在7种购买方案中选择一种,因此我要在7种购买方案中选择一个最佳情况。

       3、子问题是,我选择了某个方案后,如何使得购买剩余的书能用最少的钱?并且这个选择不会使得剩余的书为负数。母问题和子问题都是给定三卷书的购买量,求最少需要用的钱,所以有“子问题重叠”,问题中三个购买量设置为参数,分别为i、j、k。

       4、的确符合。

       5、边界是一次购买就可以买完所有的书,处理方式请读者自己考虑。

       6、每次选择最多有7种方案,并且不会同时实施其中多种,因此方案的选择互不影响,所以有“子问题独立”。

       7、我可以用minMoney[i][j][k]来保存购买第1卷i本,第2卷j本,第3卷k本时所需的最少金钱。

       8、共有x * y * z 个问题,每个问题面对7种选择,时间为:O( x * y * z * 7) =  O( x * y * z )。

       9、用函数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;

}



 转载自:http://www.cnblogs.com/sdjl/articles/1274312.html


显示接口-DP AUX - CH具有半双工、双向的物理层。接收设备可以切换HPD信号,提示源设备发起一个AUX请求事务来读取DPCD链路/接收状态寄存器位,包括IRQ_HPD矢量寄存器位。AUX - CH由一个交流耦合的双端差分对组成。主链路是一个单向、高带宽、低延迟的通道,用于传输同步数据流,如未压缩的视频和音频。AUX CH在支持的最长15米或更长电缆长度上提供1Mbps的数据速率。AUX - CH是一种半双工、双向通道,用于链路管理和设备控制。主链路由一个、两个或四个交流耦合的双端差分对(称为通道)组成。 阅读详情

相关推荐

【算法】动态规划:适合新手的动态规划入门常见题目详解

动态规划一、什么是动态规划1.官方定义2.动态规划的特点二、题目练练手1.斐波那契数列 一、什么是动态规划 1.官方定义 动态规划(英语:Dynamic programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即...

Moo_Lavender的博客 1745

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

作者:贵州大学 05级 刘永辉 由于帖子太长 分三次发 这是第一部分 对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划。本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读

杨德龙的专栏 2176

【状压DP】状态压缩动态规划入门超详解

状压DP一、概述1.状态压缩2.使用条件3.状压DP二、位运算三、例题引入入门例题【例1】填满棋盘入门例题【例二】玉米地 感觉好多讲状压DP的博客都有点乱,我就结合各路大佬的博客,加上我自己的理解,总结出一篇博客来,供初学者参考 一、概述 1.状态压缩 状态压缩就是使用某种方法,简明扼要地以最小代价来表示某种状态,通常是用一串01数字(二进制数)来表示各个点的状态。这就要求使用状态压缩的对象的点的...

繁凡さん的博客 1万+

dvi接口引脚定义_DisplayPort接口

名称:DisplayPort高清数字显示接口英文:DisplayPort插头介绍DisplayPort(简称DP)是视频电子标准协会(VESA)推动的数字式视频接口标准,订定于2006年5月;目前最新的1.4版,订定于2016年2月23日。该接口订定免认证、免授权金,发展中的新型数字式音频/视频界面,主要适应于连接电脑和显示屏,或是电脑和家庭剧院系统。有意要取代旧有的VGA、DVI和FPD-Lin...

weixin_39842271的博客 2407

动态规划详解-入门

什么是动态规划 上图中题目A是用动态规划做 而题目B是用dfs 动态规划的三种类型题 现在让我们先看一道例题 通过题目我们发现这是一道求最值问题,如果暴力时间复杂度会非常大,这时候就需要用上动态规划了 而我们求解一道动态规划的题目需要进行四步 动态规划组成部分一:确定状态 确定状态的关键点就在于最后一步操作和划分成子问题 现在我们的问题就变成了找27-ak时最少的硬币数+1 这就是划分子问题 此时我们的f(x)的含义就是最少用多少枚硬币拼出的都X 当状态分析完后 我们需要写出状态转移方程 动态

qq_43434328的博客 266

DP 1.2a标准协议

DP 1.2a标准协议

动态规划从入门到提升详解

写在开头: 这篇博客将从最开始入门动态规划,适合小白以及学过想要提高的选手,篇幅可能较长持续更新,主要是为了带学弟学妹以及自己复习而写。 大家可以根据自己的需要进行学习,下面介绍一下如何学习此博客 文章目录入门数字三角问题分析递归分析递推分析解决动态规划的一般思路 入门 要想学好动态规划首先要学好递归与递推,在此基础上才能进阶到动态规划,这个步骤是怎么来的呢? 先别急,首先我们要明白一个概念 我们写的递归程序其实就像我们的深度优先搜素(不理解的可以先去学学,不学也可以只是帮助理解,后面内容用不到),也就是深

jigsaw_zyx的博客 1555

DP1.4标准--VESA Proposed DisplayPort (DP) Standard

DP1.4标准--VESA Proposed DisplayPort (DP) Standard

DP(动态规划)入门基础详解

DP总结 ps:学了近两个月的DP,是时候总结一波了… DP基本概要: 动态规划算法把原问题视作若干个重叠子问题的逐层递进,每一个子问题的求解过程都构成一个“阶段”。在完成前一个阶段的计算后,动态规划才会执行下一阶段的计算。 无后效性 : 为了保证这些计算能够按顺序,不重复进行,动态规划要求当前阶段不会对前面的阶段产生影响的基本条件。 最优子结构性质:大多数情况下,动态规划是用来求解最优化问题。此...

qq_44341728的博客 3337

Robosuite实战:通过Xbox手柄实现机械臂6-DoF精准控制的完整指南

本文详细介绍了如何通过Xbox手柄实现机械臂的6-DoF精准控制,结合Robosuite仿真环境与MuJoCo物理引擎,提供从环境配置到代码实现的完整指南。文章重点解析了手柄映射原理、核心控制代码以及数据采集优化技巧,帮助开发者高效完成机械臂控制任务。

weixin_29169505的博客 419

AD7920实战:从咪头到ADC的音频信号采集电路设计全解析(附电路图)

本文详细解析了基于AD7920 ADC芯片的音频信号采集电路设计全流程。从驻极体咪头的驱动、AD8542运放的两级增益与偏置设计,到关键的抗混叠滤波器配置,以及ADC接口的驱动缓冲与PCB布局要点,提供了完整的实战指南与电路图,帮助开发者实现高质量音频信号采集。

red88的博客 803

动态规划详解:从入门到精通

遇到新问题时,思考如何将其分解为子问题,如何定义状态,以及状态之间如何转移。通过不断练习,你将能够识别更多适用动态规划的场景,并熟练解决各类动态规划问题。动态规划(Dynamic Programming,简称DP)是一种将复杂问题分解为更小的子问题来求解的算法思想。它特别适用于具有重叠子问题和最优子结构性质的问题。如果从A到C的最短路径经过B,那么从A到B和从B到C的路径也分别是各自的最短路径。构建最终解:从子问题的解构建原问题的解。分解问题:将原问题分解为若干个子问题。四、经典动态规划问题。

weixin_45776000的博客 1277

ZYNQ平台AXI DMA传输避坑指南:如何快速定位‘errors:200‘等中断故障

本文详细解析了ZYNQ平台AXI DMA传输中常见的'errors:200'等中断故障,提供了从寄存器解析到压力测试的完整解决方案。通过深入分析XILINX_DMA中断机制、错误分类及五步排查法,帮助开发者快速定位并解决DMA传输问题,提升系统稳定性与性能。

weixin_29159613的博客 441

【动态规划】从入门到实践---动态规划详解

1.动态规划概念 动态规划就是利用历史记录,来避免我们进行重复计算,而这些历史记录,我们需要用一些变量来保存,一般使用一维数组或者二维数组,下面我们来说动态规划最重要的三个步骤: 一.定义数组元素的含义 因为我们需要用一个数组来保存历史数据,那么最重要的来了,需要保存的历史数据是什么? 也就是数组内存放的元素含义是什么? 二.找到数组元素之间的关系表达式 也就是说,我们可以利用数组中保存的历史数据推理计算出来新的元素值,所以我们要找到数组之间元素的关系表达式,例如dp[n] = dp[n-1] + d

m0_57248981的博客 1575

【毕业设计之python系列】基于Flask的在线音乐网设计与实现

本论文旨在通过使用Python的Web框架Flask,设计和实现一个具有完整功能的在线音乐网站。该网站包括用户注册、登录、注销、歌曲上传、编辑、删除、歌单创建、编辑、删除、评论、搜索、音乐播放等功能,并针对不同用户角色(如普通用户、管理员)实现了不同的权限管理。同时,本论文还介绍了如何使用第三方API(如网易云音乐API)获取歌曲信息等技术实现。在设计上,本论文采用了MVC(Model-View-Controller)架构模式,将后端数据处理与前端展示分离,以便于代码的管理和维护。在数据库设计方面,本论文设

m0_56073435的博客 3245

8.5华为OD机试真题 新系统 - IPv4 等长子网划分与自动分配系统 (Java/Py/C/C++/Js/Go)

8.5华为OD机试真题 新系统 - IPv4 等长子网划分与自动分配系统 (Java/Py/C/C++/Js/Go)

算法大师! 526

动态规划入门详解 内含12道经典动态规划编程题

动态规划入门详解 一 什么是动态规划?? 算法导论中介绍,动态规划和分治方法类似,都是听过子问题的解来解决原问题。下面说一下这2者之间的分别,分治方法将原问题划分为互不相交的子问题,而后将子问题组合之后求出原问题的解,而动态规划是相反的,动态规划利用子问题之间的重叠,写出原问题和子问题之间的状态转移方程,转化为更小的子问题的求解,直到到达边界条件为止,有点类似于递归。 ①动态规划和分治的区别 分...

haocoming的博客 2512

Python爬虫应对Cloudflare防护:5秒盾+Turnstile验证码实战(AST反混淆+指纹模拟,成功率95%)

Cloudflare 5秒盾+Turnstile验证码的防护核心,是通过“前端JS挑战+多维度指纹校验”确认请求来源的真实性。用AST反混淆还原CF的验证逻辑,避免执行无用代码导致的验证失败;基于真实浏览器采集指纹,确保指纹维度100%匹配真人环境;结合轻量级JS引擎和自动化工具,模拟完整的浏览器执行环境。该方案的绕过成功率可达95%(剩余5%主要是IP或请求频率导致的风控),适用于绝大多数部署CF防护的网站。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1717

动态规划入门题目详解

动态规划 Dynamic Programming 1. 名称理解 Programming 是编程的意思,个人认为翻译成规划,有点不太合适。那有人就说了,人家的算法实现方式就是规划的啊。我们看看英文的解释:Simplifying a complicated problem by breaking it down into simpler sub-problems in a recursive manner. 翻译过来就是:用递归的方式将一个复杂的问题分解为简单的子问题。这不就是分治嘛。所以 Dynamic P

InterestAndFun的博客 385

Jetson AGX Orin和Drive AGX Orin相机的关联分析和编程指南

通过适当的相机接口和连接,以及使用适当的软件开发环境,开发人员可以在这些平台上实现相机功能。Jetson AGX Orin和Drive AGX Orin是NVIDIA推出的两款强大的计算平台,用于自动驾驶和人工智能应用。Jetson AGX Orin和Drive AGX Orin平台提供了强大的计算能力,使开发人员能够实现复杂的相机功能和算法。以上只是一些示例,Jetson AGX Orin和Drive AGX Orin平台提供了丰富的开发资源和工具,可用于实现各种复杂的相机应用。显示图像在一个窗口中。

CyberLynxO的博客 1122

手把手教你学Simulink--移动机器人多轮协同场景实例:基于Simulink的双轮差速PMSM轮毂电机协同驱动仿真

本文介绍了基于Simulink的双轮差速PMSM轮毂电机协同驱动仿真系统。针对移动机器人存在的电机参数不一致、负载分配不均等问题,提出主从同步+力矩补偿的协同控制策略。通过搭建包含运动学模型、PMSM电机模型和矢量控制器的仿真系统,实现了速度同步误差<0.005m/s、轨迹跟踪误差<0.8cm、能耗降低12.5%的优化效果。文章详细阐述了建模步骤、核心算法实现和性能验证,为移动机器人动力系统设计提供了实用参考方案。

MHD0815的博客 133

动态规划入门详解java实现

一到经典且简易的动态规划问题 5 //表示三角形的行数 接下来输入三角形 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上...

qq_43507104的博客 1502

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

详解动态规划入门例题

动态规划入门 文章目录动态规划入门@[TOC]简单介绍动态规划的思想例题:11.矩阵取数问题分析:代码:例题2:2.最大字段和问题代码:例题3:[3.最长公共子序列]例题4:4.编辑距离例题5:5.最长递增子序列 简单介绍 动态规划(dynamic programming),简称DP。是运筹学的一个分支,我们不会学的太深,如果想要深究,请自行学习。 我们的目的是学习DP的思想,去解决一些问题。 需...

AC是绝对不可能的 789

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

上一篇: 100层楼摔鸡蛋问题
下一篇: BWT (Burrows–Wheeler_transform) 解码分析
windroid
博客等级 码龄12年 28粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值