(发表时间: 2007-3-14 19:12:00) 【评论】 【打印】 【字体:大 中 小】 本文链接:http://blog.pfan.cn/cruxd/23967.html 复制链接 分享到: 0 tieren同学提问,“深搜和动态规划有什么区别与联系呢”,留言板上写不下,把题目扩充一下,写到这里来。 在我看来,广搜和动态规划更像些:两者都是从上往下计算,在程序中都可以从前到后分出很明显的层次。广搜采用的是队列,后进前出,队列中每一个元素需要记录下他的层次;而动归中一个状态就是一个层次。而深搜是先按第一种算法(如,搜索第一个元素)从第一层计算到最后一层,(一般而言是算那些是否有解的问题),如果发现无解倒退一层,换第二种算法(搜第二个)……依次类推。 比如在棋盘上跳马,每一步就是一个层次。在广搜中可以记录下每一步的行号列号和步数,然后推出这个记录,把它的下一步(n种情况)推入队列中。在动态规划里,扫描所有格子,跳马,在每个跳到的格子里记录下跳到该格需要的步数,这样就算一步(一个层次)。所以从记录的时间效率来看,如果棋盘足够大,显然是广度搜索合算。因为在动归里,每一步都有很多无用的格子,不记录任何东西。但是动归在棋盘足够大,步数足够多时也节约了很多空间,因为它的空间恒定为棋盘大小,而广搜则把同一个格子记录了好多遍,还附带记录了它的行号列号——前提是不做任何优化。 至于另外一种搜索——深搜,可以这样说,在那些求“是否有解”的问题中,深搜和动态规划都很有用。比如求用面值为A元,B元,C元的三种纸币能否凑出SUM元钱之类的问题。深搜处理是写一个递归,然后按某种顺序一直累加到底,若无解则回溯。动归的话可以开一个SUM的数组,初始时凑到0元。然后每一次扫描整个数组,在凑到的钱数上分别加上三种纸币,直到结束。当然也可以用广搜来做,同样是以0元为第一步,然后开始累加,这简直就是动态规划的变种了,但是同样可能会有重复记录。 那么还有一个问题,深搜和动归的效率谁优谁劣?这不是一个简单的问题。因为深搜实际上是一个二进制的问题,对于每个元素有两种选择:搜与不搜。所以如果给定N种纸币,为了简便起见,在每种纸币只许用一次的情况下,要想把所有情况遍历一遍,O(N)=2N。(因为深搜事实上得到的是一个组合,总共有2N个组合)我们也知道,二进制是一种很奇妙的东西,当N=20时只有1M,N=30时就是1个G,我的硬盘只有80个G,只容得下32个元素搜索一遍。