博文视点官方博客http://blog.csdn.net/bvbook

技术凝聚实力 专业创新出版 与向上的心合作 共同成长!

用户操作
[即时聊天] [发私信] [加为好友]
博文视点ID:bvbook
297235次访问,排名184好友187人,关注者203
博文视点读者信箱:reader@broadview.com.cn
博文视点投稿信箱:BVtougao@gmail.com
bvbook的文章
原创 254 篇
翻译 1 篇
转载 37 篇
评论 412 篇
博文视点的公告
参加读者调查,免费获取新书
博文视点,重磅推荐
博文视点,PDF最新书目
最近评论
调通:什么垃圾书都有啊
greenery:看完介绍后很有冲动拿《软件调试》来读一下
poete:to 琳琳的小狗:

这样每本书就能一样厚了~~~~:P
KKK:好书,听朋友介绍过。
interhanchi:O’REILLY的一些底层和c/c++的书怎么不出呀。。。
文章分类
收藏
    相册
    北斗星图书
    李锟先生
    图片勘误
    网络用图
    博文团队
    博文-何艳
    博文-刘唯一
    博文-刘美慧
    博文-刘薇
    博文-周筠
    博文-徐勤栋
    博文-徐定翔
    博文-晓菲
    博文-李鑫
    博文-杨小勤
    博文-杨昕宇
    博文-杨绣国
    博文-林建峰
    博文-梁晶
    博文-梅梅
    博文-梅玮
    博文-海猫
    博文-白爱萍
    博文-胡文佳
    博文-胡金贤
    博文-解娟娟
    博文-赵士威
    博文-郑丹
    博文-陈元玉
    博文-陈琼
    博文-陈蓉
    博文-马辰宇
    博文-鲁怡娜
    友情链接
    《程序员》杂志
    《软件调试》官方站点
    Dflying Chen @ cnblogs
    InfoQ的霍泰稳
    ITECN博客主编:盆盆
    RESTful Web Services中文版-网站
    博客园博文视点官方博客
    微软 武汉.NET 俱乐部
    熊力的博客——Windbg专家(RSS)
    移山之道(RSS)
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 《编程之美》读书笔记(三):烙饼问题与搜索树收藏

    新一篇: 《编程之美》读书笔记(四):买书折扣问题的贪心解法 | 旧一篇: 耳目一新的PHP5

           《编程之美》读书笔记(三):烙饼问题与搜索树
                                     作者:薛笛
    前面已经写了一些关于烙饼问题的简单分析,但因为那天太累有些意犹未尽,今天再充实一些内容那这个问题研究透。我想,通过这篇文章,我们就可以把这一类问题搞懂。再遇到优化问题,如果我们想不到别的办法,就可以采用搜索树算法来解决,至少我们不至于拿不出解决方案。前面我们已经知道,关于一摞烙饼的排序问题我们可以采用递归的方式来完成。其间我们要做的是尽量调整UpperBound和LowerBound,已减少运算次数。对于这种方法,在算法课中我们应该称之为:Tree Searching Strategy。即整个解空间为一棵搜索树,我们按照一定的策略遍历解空间,并寻找最优解。一旦找到比当前最优解更好的解,就用它替换当前最优解,并用它来进行“剪枝”操作来加速求解过程。
    书中给出的解法就是采用深度优先的方式来遍历这棵搜索树,例如要排序[4,2,1,3],最大反转次数不应该超过(4-1)*2=6次,所以搜索树的深度也不应大于6,搜索树如下图所示:
    这里只列到第三层,其中被画斜线的方块由于和上层的某一节点的状态重复而无需再扩展下去(即便扩展也不可能比有相同状态的上层节点的代价少)。我们可以看到在右子树中的一个分支,只需要用3次反转即可完成,我们的目标是如何更为快速有效的找到这一分支。直观上我们可以看到:基本的搜索方法要先从左子树开始,所以要找到本例最佳的方案的代价是很高的(利用书中的算法需要查找292次)。
    既然要遍历搜索树,就有广度优先和深度优先之分,可以分别用栈和队列来实现(当然也可以用递归的方法)。那么如何能更有效地解决问题呢?我们主要考虑一下几种方法:
    (1)       爬山法
    该方法是在深度优先的搜索过程中使用贪心方法确定搜索方向,它实际上是一种深度优先搜索策略。爬山法采用启发式侧读来排序节点的扩展顺序,其关键点就在于测度函数f(n)的定义。我们来看一下如何为上例定制代价函数f(n),以快速找到右子树中最好的那个分支(很像贪心算法,呵呵)。
    我们看到在[1,2,4,3]中,[1,2,3]已经相对有序,而[4]位与他们之间,要想另整体有序,需要4次反转;而[3,1,2,4]中,由于[4]已经就位,剩下的数变成了长度为3的子队列,而子队列中[1,2]有序,令其全体有序只需要2次反转。
    所以我们的代价函数应该如下定义:
    1 从当前状态的最后一个饼开始搜索,如果该饼在其应该在的位置(中间断开不算),则跳过;
    2 自后向前的搜索过程中,如果碰到两个数不相邻的情况,就+1
    这样我们就可以在本例中迅速找到最优分枝。因为在树的第一层
    f(2,4,1,3)=3,f(1,2,4,3)=2,f(3,1,2,4)=1,所以我们选择[3,1,2,4]那一枝,而在[3,1,2,4]的下一层:
    f(1,3,2,4)=2,f(2,1,3,4)=1,f(4,2,1,3)=2,所以我们又找到了最佳的路径。
    上面方法看似不错,但是数字比较多的时候呢?我们来看书中给出的10个数的例子:
    [3,2,1,6,5,4,9,8,7,0]程序给出的最佳翻转序列为{ 4,8,6,8,4,9}(从0开始算起)
    那么,对于搜索树的第一层,按照上面的算法我计算的结果如下:
    f(2,3,1,6,5,4,9,8,7,0)=4
           f(1,2,3,6,5,4,9,8,7,0)=3
           f(6,1,2,3,5,4,9,8,7,0)=4
           f(5,6,1,2,3,4,9,8,7,0)=3
           f(4,5,6,1,2,3,9,8,7,0)=3
           f(9,4,5,6,1,2,3,8,7,0)=4
           f(8,9,4,5,6,1,2,3,7,0)=4
    f(7,8,9,4,5,6,1,2,3,0)=3
    f(0,7,8,9,4,5,6,1,2,3)=3
    我们看到有4个分支的结果和最佳结果相同,也就是说,我们目前的代价函数还不够“一击致命”,但是这已经比书中的结果要好一些,起码我们能更快地找到最佳方案,这使得我们在此后的剪枝过程更加高效。
    爬山法的伪代码如下:
    1 构造由根组成的单元素栈S
    2 IF Top(s)是目标节点 THEN 停止;
    3 Pop(s);
    4 S的子节点按照启发式测度,由小到大的顺序压入S
    5 IF 栈空 Then 失败
    Else 返回2
     
                  如果有时间我会把爬山法解决的烙饼问题贴在后面。
    (2)       搜索策略Best-First
    最佳优先搜索策略结合了深度优先和广度优先二者的优点,它采取的策略是根据评价函数,在目前产生的所有节点中选择具有最小代价值的节点进行扩展。该策略具有全局优化的观念,而爬山法则只具有局部优化的能力。具体用小根堆来实现搜索树就可以了,这里不再赘述。
    (3)       算法A*
    如果我们把下棋比喻成解决问题,则爬山法和Best-First算法就是两个只能“看”未来一步棋的玩家。而A*算法则至少能够“看”到未来的两步棋。
    我们知道,搜索树的每一个节点的代价f*(n)=g(n)+h*(n)。其中,g(n)为从根节点到节点n的代价,这个值我们是可求的;h*(n)则是从n节点到目标节点的代价,这个值我们是无法实际算出的,只能进行估计。我们可以用下一层节点代价的最小者来替代h*(n),这也就是“看”了两步棋。可以证明,如果A*算法找到了一个解,那它一定是优化解。A*算法的描述如下:
    1. 使用BestFirst搜索树
    2. 按照上面所述对下层点n进行计算获得f*(n)的估计值f(n),并取其最小者进行扩展。
    3. 若找到目标节点,则算法停止,返回优化解
    总结:归根到底,烙饼问题之所以难于在多项式时间内解决的关键就在于我们无法为搜索树中的每一条边设定一个合理的权值。在这里,每条边的权值都是1,因为从上一个状态节点到下一个状态节点之需要一次翻转。所以我们不能简单地把每个节点的代价定义为翻转次数,而应该根据其距离最终解的接近程度来给出一个数值,而这恰恰就是该问题的难点。但是无论上面哪一种方法,都需要我们确定搜索树各个边的代价是多少,然后才能进行要么广度优先、要么深度优先、要么A*算法的估计代价。所以,在给出一个合理的代价之前,我们所有的努力都只能是帮忙“加速”,而无法真正在多项式时间内解决问题。


     

    发表于 @ 2008年04月17日 15:44:00|评论(loading...)|收藏

    新一篇: 《编程之美》读书笔记(四):买书折扣问题的贪心解法 | 旧一篇: 耳目一新的PHP5

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 博文视点