<?xml version="1.0" encoding="UTF-8" ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博文视点的博客</title><link>http://www.msdnclub.com/u/bvbook/Blog/Default.aspx</link><ttl>60</ttl><description /><generator>SpaceBuilder v1.0 正式版</generator><dc:language>zh-CN</dc:language><item><title>标题党的进步：道字大旗不再扯，美为号召又开张</title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/08/08/196.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Fri, 08 Aug 2008 06:38:31 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:196</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=196</comments><slash:comments>2</slash:comments><description><![CDATA[<p align="center"><span style="font-size: small;">&mdash;&mdash; 我读《编程之美》</span></p>
<p align="center"><span style="font-size: small;">作者：<a href="http://blog.csdn.net/aimingoo/"><font color="#6466b3">周爱民</font></a></span></p>
<p><span style="font-size: small;">题记：</span></p>
<p><span style="font-size: small;">＝＝＝＝＝＝＝＝＝</span></p>
<p><span style="font-size: small;">为拟这篇读后的标题，我花费了不少的功夫，最终我想起邹欣先生在他的博客上的一段文字，说的是上次博客堂年会上的预测之TOP。其中就有这样的一个关于书名的观点，正好引来作本文的开题。再加之本就是邹先生所述或所认可的观点，固而必当切合其书的本旨。 (</span><a href="http://blog.joycode.com/xinz/archive/2007/12/31/113262.aspx"><span style="font-size: small; color: #6466b3;">http://blog.joycode.com/xinz/archive/2007/12/31/113262.aspx</span></a><span style="font-size: small;">)</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small;">0、引子</span></p>
<p><span style="font-size: small;">＝＝＝＝＝＝＝＝＝</span></p>
<p><span style="font-size: small;">有一天，我问了方志远兄一个问题：有没有一本书，是有一个主标题，而有两个副标题的。志远兄答我说，明清或民国时期的书里可能会极偶然地有过，但那种做法在现在的书中，是找不到的。那时，我想我提出的问题大概已经足够奇怪了。</span></p>
<p><span style="font-size: small;">后来去北京参加SD2C，正好听周筠老师说要出版这样一册《编程之美&mdash;&mdash;微软技术面试心得》，当时心里就打着小鼓：一本书怎么能既讲面试心得，又讲编程之美呢？这个书名的主副标题的风马牛之怪异状，大概可以同我的那个&ldquo;两个副标题&rdquo;并肩了。</span></p>
<p><span style="font-size: small;">很好，我仍是第一时间拿到了这本书的样章。本没有打算写书评，然而看完大概，又生出悲天悯人之心来：如同邹欣先生那本《移山之道》一般，如果仅是从标题看去，大概读者会陷死在作者设计的、需要以超过249的智商、并有着袋鼠腿般弹跳力的思维来解局的假象之中而不得脱身。如此充满异能色彩的标题，其本身就提出了一个（或许也可用于面试的）题目：主副标题的背后究竟有何玄机？</span></p>
<p><span style="font-size: small;">我认为自己智商能达到要求，可以象解述《移山之道》那样为大家解释一下这个书名，以免读者走了弯路。遂决定做一做这个题目，由是写了这篇读后。</span></p>
<p><span style="font-size: small;">1、多面性：唐僧团队</span></p>
<p><span style="font-size: small;">＝＝＝＝＝＝＝＝＝</span></p>
<p><span style="font-size: small;">在写这些文字之前，我正好读到一篇有关HR的文章，是讲人事经理如何看待&ldquo;唐僧团队&rdquo;裁员的。三种人事经理／主管分别从员工价值、阶段需求和工作内容方面提出了看法。我首先觉得，从人事部门来看，这些选择无可厚非。要么量人，要么量力，要么应事之需，所以也算得好办法。 (CIO思考:假如唐僧团队裁员你会先裁掉谁, &nbsp;</span><a href="http://cio.csdn.net/page/6ee073ef-1fa8-4c8a-96d1-eba9041ac433"><span style="font-size: small; color: #6466b3;">http://cio.csdn.net/page/6ee073ef-1fa8-4c8a-96d1-eba9041ac433</span></a><span style="font-size: small;">)</span></p>
<p><span style="font-size: small;">然而，这并不见得是&ldquo;唐僧团队裁员问题&rdquo;的正确解法。因为这个问题本身是具有多面性的，不同的部门或人从各自的角度来看，都会有差异。但如果这时有一个&ldquo;充要问题&rdquo;提出，那么问题转变为单面的了&mdash;&mdash;如果你能确认这个问题是其它任何问题的前提的话。</span></p>
<p><span style="font-size: small;">例如我发现，所有HR都没有提到这样一个充要问题：唐僧团队是拿来干什么的？</span></p>
<p><span style="font-size: small;">显然，我们只是要裁员，不是要否定这个团队的目标。所以无论如何解决问题，都不能影响这个目标的达成。而&ldquo;唐僧团队&rdquo;的目标，其实是&ldquo;保护唐僧西天取经&rdquo;（参见《西游记》原著）。由此问题变得很有趣了，在这个团队中，看起来最无能、最碍事的那个人，却是最不能被裁员的。因为那个人&mdash;&mdash;唐僧是目标的一部分。</span></p>
<p><span style="font-size: small;">尽管这只给出了谁不能被裁，而不是&ldquo;裁掉谁&rdquo;的答案，但这说明：当问题由多面变为单面时，答案将变得清晰&mdash;&mdash;哪怕这个答案不是最终的解。</span></p>
<p><span style="font-size: small;">2、目标：沙漠求生</span></p>
<p><span style="font-size: small;">＝＝＝＝＝＝＝＝＝</span></p>
<p><span style="font-size: small;">问题的多面性中，最容易看到也最容易被忽略的是&ldquo;目标&rdquo;。我们大多数人容易陷入对细节或具体问题的讨论，而忘掉讨论它的原因。</span></p>
<p><span style="font-size: small;">例如我刚到盛大时，接受过两天的内训。这个内训中有一个&ldquo;沙漠求生&rdquo;问题，说飞机迫降在沙漠中了，现有十件物品需要决定其重要性，以便在必要时使用或抛弃。这个问题是由不同的小组共同协商并给出答案的。我所在的小组开始了讨论：大家对各个物品逐一衡量，然后在较小的争议的情况下达成了一致，最后用了不到五分钟，便给出了答案。在交卷时，我问了一下：我们干么要决定物品的重要性呢？我们真正的问题&ldquo;好象是&rdquo;要逃生&hellip;&hellip;但我的疑问没有被解决，答卷就交上去了。</span></p>
<p><span style="font-size: small;">内训后的评论中，讲师说：这是盛大最快的一次交卷。从答案的分数上来说，各位都很聪明，能较正确地选择这些物品。但只有一名同事提了一个问题：我们做这些选择的目的只是逃生，所以没有逃生计划的选择都是错误的。</span></p>
<p><span style="font-size: small;">在五分钟的时间里，我们没有推举出&ldquo;逃生项目&rdquo;领导者，没有制定出逃生的计划，也没有更详细的分析。我们小组用了5分钟证明大家都是可以交出90多分答卷的聪明人，但面对逃生项目，我们都失败了。</span></p>
<p><span style="font-size: small;">因为我们忽略了做这些选择，其原始的目标是什么。</span></p>
<p><span style="font-size: small;">3、从《编程之美&hellip;&hellip;》到微软的人力策略</span></p>
<p><span style="font-size: small;">＝＝＝＝＝＝＝＝＝</span></p>
<p><span style="font-size: small;">很早以前，我就听说过&ldquo;Google只招最聪明的人&rdquo;、&ldquo;微软只招最优秀的人&rdquo;。这两个人力策略其实有一个一致的陷井：如何衡量。一个、或一系列问题的&ldquo;答案&rdquo;，是否是衡量优秀与聪明的标准呢？</span></p>
<p><span style="font-size: small;">当然不是。通过类似的衡量，我们小组在&ldquo;沙漠求生&rdquo;中成了&ldquo;聪明的失败者&rdquo;。聪明与否，不是从问题的答案就可以看出来的&mdash;&mdash;能看出来的，是解决问题的能力。</span></p>
<p><span style="font-size: small;">《编程之美》列举了几十道精彩的试题，每个题目都有详细的分析和解释。你可能非常聪明，但却不会解答其中的任意一个问题。因为这些问题所展示的能力，并不见得是你所擅长的。换言之，这些问题不是为一个通常概念上的&ldquo;聪明人&rdquo;或&ldquo;优秀的人&rdquo; 而设定的，而是为一个职明或优秀的&ldquo;程序员&rdquo;而设定的。</span></p>
<p><span style="font-size: small;">在招聘这个问题上的&ldquo;充要问题&rdquo;是：招来人做什么？真正的答案是：你被招来做什么，决定了你的&ldquo;优秀&rdquo;与&ldquo;聪明&rdquo;如何被衡量。因此，如果你被招来做程序员（或其它类似的技术职位），那么（在微软亚洲工程院）衡量你方法，就是类似于《编程之美》中所列举的那些问题。</span></p>
<p><span style="font-size: small;">但是，微软并不只招程序员，IT业也并不仅仅需要程序员。</span></p>
<p><span style="font-size: small;">4、程序＝计算求值，但问题不总是有答案的</span></p>
<p><span style="font-size: small;">＝＝＝＝＝＝＝＝＝</span></p>
<p><span style="font-size: small;">如果我们把一个问题看成总是有结果的，那么我们总是可以把这个问题抽象为可计算的模型并求值。如果作为人&mdash;&mdash;世界的观察者，我们面临的问题都是这种类型的，那种世界必然是程序化的。</span></p>
<p><span style="font-size: small;">然而，世界不是程序化的。所以，你面临的问题也不是必然有结果的。</span></p>
<p><span style="font-size: small;">我终于理解为什么这本书是叫《编程之美》，而将&ldquo;面试&rdquo;作为它的副标题。&ldquo;在微软的技术面试&rdquo;，在这本书中被局限在一个&ldquo;做程序员&rdquo;的范围之内。这本书设定的目标是：如果你想向微软证明你可以是合格的程序员，那么你就解决这些程序化的问题。</span></p>
<p><span style="font-size: small;">而我大概是没有这个&ldquo;在微软做程序员&rdquo;的命了，因为在我看来，问题的复杂性在于它的无解，而不在于它的有解。无解的问题如同一只海胆，你从哪方面看去都是问题，你必须拔了那些刺&mdash;&mdash;既是问题的边角，也是问题的根源，然后你才会看到问题的真相：海胆原来只是一堆细胞。</span></p>
<p><span style="font-size: small;">5、你的目标是什么？</span></p>
<p><span style="font-size: small;">＝＝＝＝＝＝＝＝＝</span></p>
<p><span style="font-size: small;">如同&ldquo;唐僧团队&rdquo;问题所表现出来的：（若非特殊情况，）HR不会为某个团队需要什么人而招聘，HR的作用是为构建公司的人力体系而招聘。他的条件是&ldquo;符合公司需要的（例如聪明的或优秀的）、有充分价值的&rdquo;人才。前提是：这些人才的选择，是在某种领域中可量化考核的。</span></p>
<p><span style="font-size: small;">你的目标是什么呢？是微软吗？或者是微软亚洲研究院？更或者是一名开发人员？你的目标到底是一个公司，还是一份工作呢？你是热爱这个公司，还是热爱这个工作呢？你的目标所需要的能力是什么？你的能力又是什么呢？</span></p>
<p><span style="font-size: small;">这些都是问题。然而，如果你不弄清这些问题而去读《&hellip;&hellip;&mdash;&mdash;微软技术面试心得》，就不是问道于盲，而是盲人问道了。</span></p>
<p><span style="font-size: small;">6. 总结</span></p>
<p><span style="font-size: small;">＝＝＝＝＝＝＝＝＝</span></p>
<p><span style="font-size: small;">在我而言，邹先生的考题是&ldquo;这本书的书名为什么是这样&rdquo;，而我的答案是：看到问题的多面性，看到问题的目标。</span></p>
<p><span style="font-size: small;">一本书要作为两本书来读：编程之美讲编程，面试心得讲面试。至于书名上还写着的&ldquo;微软&rdquo;两个字，正好是作者组成员们的身份。一个书名里头讲了三件事，正好比我那个&ldquo;两个副标题&rdquo;的问题&mdash;&mdash;虽然很奇怪，但总有其内在的道理。</span></p>
<p><span style="font-size: small;">书的好与不好，不要总盯在书名上。分开来看，这本书在编程与面试两个部分写得都非常精彩。&ldquo;想做程序员&rdquo;如同&ldquo;想做科学家&rdquo;一样，如今都快被人拿来做笑谈了，但是这两种意愿却完全没错，也相等同的崇高。所以想做程序员的人不必怕着了那些流言，自按自的道去走就好了。而同样的原因，这本书的精彩与不精彩，也不必听着了那些闲杂碎语，便有畏怯之心，摆正了一个程序员的心态，或者一个面试者的心态去读就好了。</span></p>
<p><span style="font-size: small;">这本书不会只给你答案，还会教给你思考问题的方法&mdash;&mdash;所以它是一本好书。而我这篇文章， </span><span style="font-size: small;">并不是讲一本书好或不好的书评，而只是教给你思考问题的方法&mdash;&mdash;所以它算不上一篇好的读后。然而我之现在，已然少了&ldquo;好或不好&rdquo;的评价欲望，时时升腾在我心中的，是面向问题时的那种折返不息的浪潮&mdash;&mdash;我甚至不关心浪潮的扑打，而只把眼光投向洋流的来向。</span></p>
<p><span style="font-size: small;">原博客地址：<a href="http://blog.csdn.net/aimingoo/archive/2008/06/12/2541941.aspx"><font color="#6466b3">http://blog.csdn.net/aimingoo/archive/2008/06/12/2541941.aspx</font></a></span></p><img src="http://www.msdnclub.com/utility/AggView.ashx?ViewObject=7&PostID=196" width="1" height="1">]]></description></item><item><title>《编程之美——微软技术面试心得》面试小故事（二）</title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/08/08/195.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Fri, 08 Aug 2008 06:36:52 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:195</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=195</comments><slash:comments>3</slash:comments><description><![CDATA[<p><span style="font-size: small;">A今天去面试，一路过关斩将，到了一个gg面前，他也问了今年的流行语 &ndash; 看了编程之美？<br />答: 是。<br />问：从头到尾都看了？<br />答：是的，我还发现了几个小错误。<br />问：那我问你一个书上的问题，一模一样，你应该有信心作出来吧？<br />答：当然。&nbsp; <br />问：书带来了，好，请放在桌上。<br />A只好把书摆在桌面上，不知道他葫芦里卖的什么药。。。<br />这位gg弯腰在抽屉里摸索了一会儿，拿出一个丁零当啷响的东西，仔细地摆在桌面上。摆得和书的封面一模一样。<br />gg 面带微笑地说：&nbsp; 那就把这个九连环解出来吧。</span> </p><img src="http://www.msdnclub.com/utility/AggView.ashx?ViewObject=7&PostID=195" width="1" height="1">]]></description></item><item><title>《编程之美》背后的作者之美 </title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/08/04/185.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Mon, 04 Aug 2008 01:58:56 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:185</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=185</comments><slash:comments>1</slash:comments><description><![CDATA[<h2 style="text-align: center;"><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/bvbook/EntryImages/20080804/s3006527.jpg" alt="" width="200" height="252" /></h2>
<p align="center"><span style="color: black;">作者：<a href="http://blog.csdn.net/futurelight/"><span style="color: black;">InfoQ</span><span style="color: black; font-family: 宋体;">中文站总编辑</span><span style="color: #770000;"> </span><span style="color: black; font-family: 宋体;">霍泰稳</span></a></span></p>
<p>&nbsp;&nbsp; &nbsp;&nbsp; <span style="color: black; font-family: 宋体;">收到<a class="null" href="http://www.china-pub.com/38070"><span style="color: #770000;">《编程之美》</span></a>这本书的时候，我是悲喜交集的。喜的是可以从中了解一下微软是如何做面试的，和其他的软件公司有什么区别，这可能是我长期从事编辑的毛病，遇事总爱比较一番；悲的是我发现上面的绝大多数面试题目我都看不懂，更悲的是我还是一个计算机科班出身的人，看来今后再也不能随便给别人吹嘘我曾经还学习过什么数据结构、编译原理什么的。</span></p>
<p><span style="color: black; font-family: 宋体;"><span style="font-family: Verdana;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>本书作者邹欣老师一直是我很崇拜的人，事业有成（在我看来毕业于国外名校，而且能在微软研究院待很久的人都是事业有成的），家庭幸福（夫人漂亮，小女考试经常双百），心态平和（很少见其动怒，总是一副深思的样子），而且文笔了得（已经写过一本<a class="null" href="http://www.china-pub.com/35373"><span style="color: #770000;">《移山之道》</span></a>的书，</span><span style="color: black;"><a href="http://www.infoq.com/cn"><span style="color: black;">InfoQ</span><span style="color: black; font-family: 宋体;">中文站</span></a></span><span style="color: black; font-family: 宋体;">上有样章发布）。在我从前编辑《</span><span style="color: black;">MSDN</span><span style="color: black; font-family: 宋体;">开发精选》的时候就打过交道，在和他的沟通中，了解到他的注意力不仅仅是自己在研究院里的一亩三分地，还常常发感慨说如何能为国内的技术社区多做点事情，如何能帮助的中国的开发人员多做点事情，我想《编程之美》的最终完成应该是符合他的这个感慨的。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: black; font-family: 宋体;">这本书的价值，我想看过此书的朋友应该是有所感触的，另外从这本书的畅销也能有所体察。在工作过程中，我也经常面试人，不论是从前从事软件开发的时候还是现在做编辑。经常困扰的一个地方是，通过和被面试者的交谈，我们可以基本了解这个人的品行、工作态度如何，但是要了解他的专业能力是难上加难。虽然一个人有了热情，可以在以后的工作中比较快地追赶上来，但是&ldquo;万丈高楼平地起&rdquo;又往往不是一个中小型公司所需要的，他们通常没有那么多的时间和财力来对新人进行培训。《编程之美》从某种程度上，我认为可以帮助软件公司里面的技术主管解决这个问题。另外一方面，很多时候，面试求职者又对所求公司的要求摸不着头脑，一轮一轮面试下来，一次一次打击下来，挫折感倍增。如果有内部人士将自己身居高堂的经验抖落一下，哪怕是点滴之言，对他们也是有百益而无一害。微软作为软件公司的代表，《编程之美》作为其面试过程的总结，应该可以帮助万千编程人员一解面试之苦。</span></p>
<p><span style="color: black; font-family: 宋体;"><span style="color: #0000ff;"><span style="color: #0000ff; font-family: 宋体;"><span style="color: #000000;"><span style="color: #000000; font-family: 宋体;"><span style="font-family: 宋体;">&nbsp;&nbsp;&nbsp;&nbsp;当然，如果只是照本宣科，从书中摘选一些题目用于面试，这肯定不是本书作者的原意。</span>其实从书中我们可以了解到，作者更希望让面试者和被面试者都能够有所觉悟，都能够从&ldquo;美&rdquo;的角度看待编程，</span></span></span></span>将编程人员和&ldquo;</span><span style="color: black;">IT</span><span style="color: black; font-family: 宋体;">民工&rdquo;&ldquo;软件蓝领&rdquo;区别开来。话说回来，编程本是高尚的，只是不高尚的人误以为不高尚罢了。授之以鱼，不若授之以渔，希望读者能理解作者的苦心！</span></p><img src="http://www.msdnclub.com/utility/AggView.ashx?ViewObject=7&PostID=185" width="1" height="1">]]></description></item><item><title>性能调优的步骤</title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/08/01/183.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Fri, 01 Aug 2008 10:16:11 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:183</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=183</comments><slash:comments>1</slash:comments><description><![CDATA[<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">性能调校的工作千头万绪，最怕的就是像无头苍蝇般盲目地错误尝试（</span><span><span style="font-family: Times New Roman;">trial and error</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">），不但旷日费时，还累积不到经验，团队与个人都难以成长，也就是说下次再碰到性能议题时，还是乱试一通。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">我们需要拟定计划、有步骤分阶段地执行，如此才能循序渐进，一步步朝目标前进。据微软的研究显示，过程应该分为</span><span><span style="font-family: Times New Roman;">6</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">个阶段，分别是发现、探究、提案、执行、复查、收尾。这不一定适用于任何调校的情境，笔者从来也没有完全这么做，但却是个可供参考的方法论，能据以修正成自己的方法。有固定的准则后，才可以累积经验并加以分门别类。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">现将各步骤的原文列出如下：</span></span></p>
<p class="a0" style="margin: 4pt 0cm 4pt 37.15pt;"><span style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings;"><span style="mso-list: Ignore;"><span style="font-size: x-small;"></span><span style="font: 7pt 'Times New Roman';"><span style="font-size: x-small;">&nbsp; </span></span></span></span><span style="font-size: x-small;"><span><span style="font-family: Times New Roman;">Discover the problem</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">：发现问题。</span></span></p>
<p class="a0" style="margin: 4pt 0cm 4pt 37.15pt;"><span style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings;"><span style="mso-list: Ignore;"><span style="font-size: x-small;"></span><span style="font: 7pt 'Times New Roman';"><span style="font-size: x-small;">&nbsp; </span></span></span></span><span style="font-size: x-small;"><span><span style="font-family: Times New Roman;">Explore the conditions</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">：探究原因，为问题提供明确的定义与定位。</span></span></p>
<p class="a0" style="margin: 4pt 0cm 4pt 37.15pt;"><span style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings;"><span style="mso-list: Ignore;"><span style="font-size: x-small;"></span><span style="font: 7pt 'Times New Roman';"><span style="font-size: x-small;">&nbsp; </span></span></span></span><span style="font-size: x-small;"><span><span style="font-family: Times New Roman;">Track down possible approaches</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">：提供可能的解决方案。</span></span></p>
<p class="a0" style="margin: 4pt 0cm 4pt 37.15pt;"><span style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings;"><span style="mso-list: Ignore;"><span style="font-size: x-small;"></span><span style="font: 7pt 'Times New Roman';"><span style="font-size: x-small;">&nbsp; </span></span></span></span><span style="font-size: x-small;"><span><span style="font-family: Times New Roman;">Execute the most likely approach</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">：执行最有可能的解决方案。</span></span></p>
<p class="a0" style="margin: 4pt 0cm 4pt 37.15pt;"><span style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings;"><span style="mso-list: Ignore;"><span style="font-size: x-small;"></span><span style="font: 7pt 'Times New Roman';"><span style="font-size: x-small;">&nbsp; </span></span></span></span><span style="font-size: x-small;"><span><span style="font-family: Times New Roman;">Check for success</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">（如果需要的话，重复之前的步骤）：确认解决方案成功与否。</span></span></p>
<p class="a0" style="margin: 4pt 0cm 4pt 37.15pt;"><span style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings;"><span style="mso-list: Ignore;"><span style="font-size: x-small;"></span><span style="font: 7pt 'Times New Roman';"><span style="font-size: x-small;">&nbsp; </span></span></span></span><span style="font-size: x-small;"><span><span style="font-family: Times New Roman;">Tie up loose ends</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">：完成收尾的工作。</span></span></p>
<h3 style="margin: 12pt 0cm 7.5pt;"><span style="font-size: large;"><span style="mso-fareast-language: ZH-CN;">1.3.1</span><span style="mso-fareast-language: ZH-CN;"><span style="mso-spacerun: yes;">&nbsp; </span></span><span style="mso-fareast-language: ZH-CN;">各阶段重点说明</span></span></h3>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">以下对各阶段稍做说明。</span></span></p>
<p class="4" style="margin: 7.5pt 0cm;"><span style="font-family: 方正细黑一简体;"><span style="font-size: x-small;">1.3.1.1<span style="mso-spacerun: yes;">&nbsp; </span>发现问题</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">这可能是支持性能调校的专家们花时间最少的一个阶段，因为大部分的工作都是用户在做，他们可能已经有一大堆的观察经验，而找你来，不会期望你完全重做一遍他们已经做过多次的事情，而是希望看到你马上采取一些行动，并一针见效。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">这个阶段专业与否就看你是否可以立刻找到重点，把握住各个细节，而不是在整个调校的各个程序中，来来回回、反反复复询问相同的问题。这个阶段最重要的就是发现（</span><span><span style="font-family: Times New Roman;">Discover</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">）问题、详述（</span><span><span style="font-family: Times New Roman;">Describe</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">）问题，并且正确而详细地记录下来（</span><span><span style="font-family: Times New Roman;">Document</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">）。在进入下一步骤前，你应该问问自己以下这些问题。</span></span></p>
<h5 style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-family: 黑体; mso-ascii-font-family: Arial; mso-fareast-language: ZH-CN;">对于问题是否已经有简明的描述</span></h5>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">若无法简明地描述问题，代表你尚不了解问题，或者没抓到重点。这是很有可能的，因为用户常拉拉杂杂地说了一大堆，让你晕头转向，只好急着做点东西，不见得是有方向，只是想摆脱用户像倾倒垃圾一样，噼里啪啦地描述现象时，还夹缠着抱怨与谩骂，大家一拥而上，对你一股脑儿地说个不停。信息虽然多，但零零碎碎看不到全貌。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">你可以尝试将自己听到的，重新有序地整理一遍再诉说给用户听，看看是否符合大家共通的观点，若没有异议，就有了一个大致正确的开始。</span></span></p>
<h5 style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-family: 黑体; mso-ascii-font-family: Arial; mso-fareast-language: ZH-CN;">用户的基线与期待在哪</span></h5>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">在前面一节中强调了基线的重要，这让你可以比较成果，并有前进的目标。例如，当用户抱怨&ldquo;</span><span><span style="font-family: Times New Roman;">SQL Server </span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">跑得太慢了&rdquo;，这时要理清他们的&ldquo;慢&rdquo;是怎么定义的，而什么是合理可接受的速度。若没有基线，则需要你为他们建立。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">性能调校可能是一再循环的过程，除了时间难以掌握外，还不一定所有的问题都有解。不要让用户有错误或过高的期待，从而能减少承担不可能完成任务的压力，更可减少长时间调校后，达不到用户期望而招致的愤怒。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">在查找的过程中尽量不要急躁或恐慌，贸然进入到下一个步骤，只会让你再一次回到原点，重新定义问题。</span></span></p>
<p class="4" style="margin: 7.5pt 0cm;"><span style="font-family: 方正细黑一简体;"><span style="font-size: x-small;">1.3.1.2<span style="mso-spacerun: yes;">&nbsp; </span>探究原因，为问题提供明确的定义与定位</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">确定用户的问题与需求后，下一步是探究原因，此步骤的重点是&ldquo;探索（</span><span><span style="font-family: Times New Roman;">Explore</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">）&rdquo;、&ldquo;找寻证据（</span><span><span style="font-family: Times New Roman;">Evidence</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">）&rdquo;、&ldquo;建立（</span><span><span style="font-family: Times New Roman;">Establish</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">）&rdquo;描述整个问题来龙去脉的假设。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">当你从以上步骤确切了解用户的问题后，就需要建立问题发生原因的假设和导致性能不足的运行模型，而当前这个步骤便是在搜集证据，以建立并确认该假设。在这个阶段中，你可以通过</span><span><span style="font-family: Times New Roman;">SQL Server Management Studio</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">、</span><span><span style="font-family: Times New Roman;">SqlDiag.exe</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">、性能计数器、事件查看器、</span><span><span style="font-family: Times New Roman;">SQL Profiler</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">、</span><span><span style="font-family: Times New Roman;">SQL Server 2005 Performance Dashbord Reports</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">、</span><span><span style="font-family: Times New Roman;">DMV</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">与</span><span><span style="font-family: Times New Roman;">DMF</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">等工具来找线索（以上工具在本书第</span><span><span style="font-family: Times New Roman;">3</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">章&ldquo;性能调校相关工具程序&rdquo;中有详细说明）。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">这个步骤的主要任务是广泛搜集相关数据，但并未深入分析数据间的关联性，这是下一步骤要做的事情。当然，要搜集正确而相关的证据，难免要稍做分析，但不要过度耗时在某项单一的事件上。此步骤要的是全貌，尽量了解系统的每一个方面，避免深入分析时，漏了某个关键现象而误入歧途。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">当然，若在这个阶段就发现重大问题，一眼就看出关键点，例如，硬件毁损，某个硬盘区间或内存区间不稳，某个程序吃掉所有的内存，让</span><span><span style="font-family: Times New Roman;">SQL Server</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">无内存可用，抑或是该程序常常出问题，拖垮</span><span><span style="font-family: Times New Roman;">CPU</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">等，则可以跳过</span><span><span style="font-family: Times New Roman;">DETECT</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">方法论之后的步骤，进行深入探讨这个问题并予以解决。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">通常性能调校并不是那么容易一眼看出重大错误，或许用户自己就可以解决，而需要专门做性能调校的情况可能如战场上不断带来的伤患，第一步要做的是决定伤患的轻重，再决定如何利用有限的资源做最有效的治疗。当你在前一步获得用户大量的问题后，接下来就要搜集并探究各种现象，决定轻重缓急，通盘考虑后，进入下一步。</span></span></p>
<p class="4" style="margin: 7.5pt 0cm;"><span style="font-family: 方正细黑一简体;"><span style="font-size: x-small;">1.3.1.3<span style="mso-spacerun: yes;">&nbsp; </span>提供可能的解决方案</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">在深入分析前述两步骤搜集到的数据，并对整个问题的前因后果提出假设，进而拟出对应策略，如果前一个步骤做得不够详实，就可能误判，导致努力了半天，但没有碰到瓶颈点。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">在拟定策略时，应当参考大量的在线说明、</span><span><span style="font-family: Times New Roman;">Knowledge Base</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，在网络上广泛查找资料，看看前人或是微软对于你所面对的问题是否有好的方案。到相关网站讨论区提出问题，或是询问技术顾问，最好不要闭门造车，防止解决问题时又出现新问题。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">这个步骤最重要的是拟定计划，而这又可分为两个部分：用来证明对问题所建立的假设的计划，以及解决问题的计划。前文一再强调，性能调校可能是个一再循环的过程，有一个好的计划，你才能知道方向与步骤。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">不要冲动地进入到下一步骤，信息界有句名言：&ldquo;最早开始的，最晚结束&rdquo;。言下之意就是凡事要谋定而后动，若匆忙进入到下一步执行解决方案，可能因为疏失而导致更多的错误，甚至因为你的操作让系统更为不稳定，原本性能不佳的系统宕掉了，这时会招致用户更大的不满。</span></span></p>
<p class="4" style="margin: 7.5pt 0cm; line-height: 17pt;"><span style="font-family: 方正细黑一简体;"><span style="font-size: x-small;">1.3.1.4<span style="mso-spacerun: yes;">&nbsp; </span>执行最有可能的解决方案</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">这可能是</span><span><span style="font-family: Times New Roman;">DETECT </span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">方法中最简单的一步，因为只要执行上一步中所拟定的计划即可。但是在执行计划时，仍然要注意系统的反应，随时都可能会要放弃当前的计划，因为新的证据可能证明先前的判断是错误的，因而要修正计划，甚至是退回到重新拟定计划。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">随时反省，不要急着操作。每一步愈稳也就愈少反复，因此，现在的时间花费可以节省未来的时间（</span><span><span style="font-family: Times New Roman;">Spend time now to save time later</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">）。整个性能调校的过程就是在考验团队的细心与耐力、知识的广度与深度，切勿急躁。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">在这一部分执行的计划也有二个，分别是上一步拟定的：其一是对问题的假设，验证某些行为导致性能不足的计划；其二是解决问题的计划。先证明假设成立，再执行解决该问题的方案。若假设错误，当然就不需要执行解决方案。否则努力地重载了程序、变更了数据库架构、买了新的硬件等，却是验证了瓶颈点不在此，结果就尴尬了。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">同时要小心观察你的计划会不会导致新的问题，并严重影响当前系统的执行，不要原来是系统迟缓，而你的测试却成了压垮骆驼的最后一根稻草。</span></span></p>
<p class="4" style="margin: 7.5pt 0cm;"><span style="font-family: 方正细黑一简体;"><span style="font-size: x-small;">1.3.1.5<span style="mso-spacerun: yes;">&nbsp; </span>确认解决方案成功与否</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">执行计划后，需要重新收集数据，以验证该计划成功与否。这一步骤又分两个阶段，第一阶段是确认计划是否证实了假设，若证实假设是对的，则需要继续搜集相关的数据，以确立接下来的步骤。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">第二阶段是分析已收集到的数据，看看是否解决了优先级最高的瓶颈，若已解决，应有瓶颈转移的现象，此时要针对次要瓶颈开始拟定新的计划，并确定是否已经符合用户的目标。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">如果执行结果不如预期，证明假设错误，会非常让人气馁。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17.3pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">其实，定错性能调校的目标是常有的事，这时就是要你在错误的面前，停下来好好思考，不要立刻行动。查看先前步骤的各项产出，重新理出头绪，最重要的是清楚知道这一回的错误在哪，如此新的步骤就会更逼近目标。犯错是常有的事，踩着错误走向成功是性能调校的常态。现在，你可以休息一下，喝杯咖啡，和合作伙伴放轻松，回顾一下这个过程，对整个问题建立更清晰的轮廓。</span></span></p>
<p class="4" style="margin: 7.5pt 0cm;"><span style="font-family: 方正细黑一简体;"><span style="font-size: x-small;"><span style="mso-ansi-language: EN-US;">1.3.1</span><span style="mso-ansi-language: EN-US;">.6<span style="mso-spacerun: yes;">&nbsp; </span></span>完成收尾的工作</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">前</span><span><span style="font-family: Times New Roman;">5</span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">个步骤循环重复地执行，每一次循环的结果都更逼近问题的核心，直到达到性能调校的目标。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">但当我们完成目标后，依然要注意以下的问题。</span></span></p>
<p class="a0" style="margin: 4pt 0cm 4pt 37.15pt; line-height: 17pt;"><span style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings;"><span style="mso-list: Ignore;"><span style="font-size: x-small;"></span><span style="font: 7pt 'Times New Roman';"><span style="font-size: x-small;">&nbsp; </span></span></span></span><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">解决的方式是否有边际效应而造成其他的问题？</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">例如，为了某类的查询工作建立了大量的索引，事后原本正常的添加、修改、删除都出现了性能问题。</span></span></p>
<p class="a0" style="margin: 4pt 0cm 4pt 37.15pt; line-height: 17pt;"><span style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings;"><span style="mso-list: Ignore;"><span style="font-size: x-small;"></span><span style="font: 7pt 'Times New Roman';"><span style="font-size: x-small;">&nbsp; </span></span></span></span><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">是否真正根除了问题，还是仅表象地头痛医头，脚痛医脚？</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt; line-height: 17pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">建立问题的假设时，很容易将问题特殊化，仅局部地解决该问题。例如，加了某个索引或稍稍改变查询语句，舒缓了当前的瓶颈，但当用户稍微增加或采用不同的查询方式时，老问题就容易复发。</span></span></p>
<p class="a0" style="margin: 4pt 0cm 4pt 37.15pt; line-height: 17pt;"><span style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings;"><span style="mso-list: Ignore;"><span style="font-size: x-small;"></span><span style="font: 7pt 'Times New Roman';"><span style="font-size: x-small;">&nbsp; </span></span></span></span><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">是否要建立持续跟踪的计划？</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-size: x-small;">当你无法确定已经根除问题时，那可能就要拟定持续跟踪的计划了。决定是否要持续观察某些计数器，跟踪某些现象是否还会发生，若发生了要如何解决等。如此不但可以让用户安心，更可以让你知道之前的行为到底有多少效益，下次的性能调校才能提出更完整的解决方案。</span></span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span><span style="font-size: x-small;">摘自胡百敬著作《SQL Server 2005 performance tunning性能调校</span>》</span></p>
<p class="a" style="margin: 4pt 0cm; text-indent: 19pt;"><span><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/bvbook/EntryImages/20080730/SQL%20Server%202005%20Performance%20Tuning性能调校封面正面.jpg" alt="" width="185" height="230" /></span></p><img src="http://www.msdnclub.com/utility/AggView.ashx?ViewObject=7&PostID=183" width="1" height="1">]]></description></item><item><title>《Windows Workflow Foundation新一代工作流开发实务》推荐序</title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/07/30/173.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Wed, 30 Jul 2008 06:14:49 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:173</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=173</comments><slash:comments>0</slash:comments><description><![CDATA[<p>&nbsp;</p>
<p style="text-align: center;"><img src="http://images.china-pub.com/ebook35001-40000/39883/zcover.jpg" border="0" alt="Windows Workflow Foundation新一代工作流开发实务" /></p>
<p>讲到Workflow，很可能有人会立刻想到比尔&bull;盖茨常常向人推荐的一本书&mdash;&mdash;《世界是平的》。作者托马斯&bull;佛里德曼在他的著作中提到的抹平世界的十辆推土机，其中第三辆就是工作流软件。对照《Windows Workflow Foundation新一代工作流开发实务》书里的分析，再看看.NET Framework 3.0的出现，你应该可以感受到这股潮流。</p>
<p>很多人怀疑，从.NET Framework 3.0之后所增加的三大功能&mdash;&mdash;WPF、WCF、WF中，WPF着重在炫酷的UI画面，WCF则减轻开发人员在现今复杂的多平台中沟通各种通信协议的痛苦，这些都很容易理解。可是，第三个&ldquo;基础&rdquo;，为什么是一般开发人员很少去注意的Workflow？为什么不是其他功能？不管过去你熟不熟悉Workflow，WF的出现，说明了微软把Workflow当作是未来软件开发中，必然被重复使用的一个关键技术（因而称为&ldquo;基础&rdquo;，Foundation），也因为WF自然地变成一个基础，所以也很自然地可以和WPF、WCF，甚至ASP.NET整合（用WF来控制ASP.NET页面流程），都让Workflow的观念自然而然地使用，而不像过去Workflow似乎是企业才会用到的玩意儿。</p>
<p>.NET Framework 3.0正式推出已经一年多了，不过，市面上看到的几乎都是炫酷的WPF书籍，虽然&ldquo;表面&rdquo;工夫很重要，但是很高兴靖灏前辈和智桦前辈带给我们一本中文的WF著作。虽然WF这个东西本质上不像WPF那么炫，但绝对是属于&ldquo;精神&rdquo;层面的心灵滋润，而我也相信，以他们两位平常在研讨会上说故事的能力，一定可让读者在看完这本书（《<a class="null" href="http://course.china-pub.com/39883">Windows Workflow Foundation新一代工作流开发实务</a>》）之后，将这个软件开发必备的技能发挥得淋漓尽致。</p>
<p style="text-align: right;">王&nbsp; 森&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />开发技术推广经理<br />台湾微软 开发工具与平台推广处</p><img src="http://www.msdnclub.com/utility/AggView.ashx?ViewObject=7&PostID=173" width="1" height="1">]]></description></item><item><title>《编程之美——微软面试技术心得》面试小故事（一）</title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/07/30/172.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Wed, 30 Jul 2008 03:42:37 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:172</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=172</comments><slash:comments>0</slash:comments><description><![CDATA[<p>今天我去面试，前面答得还不错，最后面试官问：看了《编程之美》了么？<br />我回答：看了。<br />问：怪不得，书带来了么？<br />我从书包里拿出皱巴巴的书。<br />问：为什么书这么皱？你在上面乱画了什么？好像还被水泡过。。。<br />我想起来面试的时候要诚实，就鼓起勇气说：我有一次做题的时候趴在上面睡着了，然后流了很多口水。。。<br />面试官想了想，说：比尔开始写程序的时候，也是趴在电脑上睡着了。。。 你明天就来上班吧。</p><img src="http://www.msdnclub.com/utility/AggView.ashx?ViewObject=7&PostID=172" width="1" height="1">]]></description></item><item><title>《编程之美》读书笔记（五）：买书折扣问题的贪心解法</title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/07/30/171.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Wed, 30 Jul 2008 03:37:03 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:171</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=171</comments><slash:comments>0</slash:comments><description><![CDATA[<div style="margin: 7.8pt 0cm 15.6pt;"><span style="font-size: xx-large;"><strong><span style="font-size: 16pt;">作者：<a class="null" href="http://blog.csdn.net/kabini">薛笛</a></span></strong></span></div>
<div style="margin: 0cm 0cm 7.8pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>每次看完《编程之美》中的问题，想要亲自演算一下或深入思考的时候，都觉得时间过得很快，动辄一两个小时，如果再把代码敲一遍的话，需要的时间可能更长，真是搞不懂通过微软面试的那些家伙的脑袋到底什么构造，书的序言中提到他们每次面试45分钟，还要写出程序？！在我看来，如果是控制CPU曲线或是中国象棋问题或许还有可能，如果是买书折扣问题，我觉得真的是不太容易，尤其是如果当面试者钻进本题的贪心解法而不是动态规划算法的思路之后，因为我写这篇文章前前后后大概用了5个小时<span> :-( </span>。不过我想只要是学习就不是浪费时间，今天上网看到微软的校园招聘网站又有更新，等我把这本书看完，就投简历过去试一试 :-) 。</div>
<div style="margin: 7.8pt 0cm 15.6pt 21.25pt; text-indent: -21.25pt;"><strong><span style="font-size: x-large;"><span><span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal;"><font size="5">1</font> </span></span></span><span style="font-size: large;">问题描述及分析</span></strong></div>
<div style="margin: 0cm 0cm 7.8pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>买书折扣问题的描述是，某出版社的《哈里波特》系列共有5卷，每本单卖都是8块钱，如果读者一次购买不同的k（k&gt;=2）卷，就可以享受不同的折扣优惠，如下所示：</div>
<p style="margin: 0cm 0cm 7.8pt;" align="center"><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/kabini/program-beauty-2-0.PNG" alt="" /></p>
<div style="margin: 0cm 0cm 7.8pt;">问题是如果给定一个订单，如何计算出最大的折扣数？</div>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 21pt;">书中给出的动态规划解法这里就不再赘述了。不过，里面有两个问题需要单独关注一下：(1)如果订单描述为（X<sub>1</sub>，X<sub>2</sub>，X<sub>3</sub>，X<sub>4</sub>，X<sub>5</sub>），其中X<sub>1</sub>-X<sub>5</sub>为所订数的数量，其所在位置为卷的编号，即第一卷X<sub>1</sub>本，第二卷X<sub>2</sub>本，&hellip;，第5卷X<sub>5</sub>本；如果订单为：（X<sub>3</sub>，X<sub>2</sub>，X<sub>4</sub>，X<sub>5</sub>，X<sub>1</sub>），则表示第一卷X<sub>3</sub>本，第二卷X<sub>2</sub>本，&hellip;，第五卷X<sub>1</sub>本。我们可以很容易的看到，由于每本书的价格相同，所以折扣的多少仅仅在于如何选取而不在于究竟取那一卷书。因此，上面两个订单的最大折扣数是相同的，这也使得我们可以使用统一的方法（Y1，Y2，Y3，Y4，Y5），其中Y1&ge;Y1&ge;Y1&ge;Y1&ge;<span>Y5，来表示一个订单</span>。作者将每本书的定价设为相同的是为了简化问题，因为如果每本书的定价也不同，则问题就会变得更加复杂，这时我们就不能仅仅考虑选几本书，还要考虑选哪几本。(2)书中说对于一次选择4至2本书的情况，（以3本书为例）只需考虑F（Y<sub>1</sub>-1，Y<sub>2</sub>-1，Y<sub>3</sub>-1，Y<sub>4</sub>，Y<sub>5</sub>）的情况就可以了（注意，F为订单总价计算函数），并说&ldquo;<strong>这样选择能够保证在选择当前折扣的情况下，剩下的书的种类最多，</strong><strong>它比其它组合都好</strong>&rdquo;。我觉得这个结论并不显然，下一步可选的书的种类多就能证明这个子问题比别的子问题更好？这点我不敢苟同，须知该问题的解决是一个多步选择的过程，所以要得到这个结论就需要严格证明。如果这个条件不成立，那么书中给出的递归式也就不成立，即不能证明优化子结构性质成立。所以，对于如此重要的细节，书中应该给出严格证明而不是一句话带过。</div>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 21pt;">刚开始拿到问题的时候就条件反射地想能不能用贪心算法，即每次都尽量按最大折扣来取书。书中给出一个反例：所给的订单是（2，2，2，1，1），按照贪心算法，我们的选择方式是5+3，其折扣为5*0.25+3*0.10=1.55；而如果采用4+4的模式，则折扣数为2*4*0.20=1.6。这显然违背了贪心规则。所以书中在解法二中采用了另外一种分析，作者计算了订单中书的数量在[1-10]区间内，各种不同的选取方法所能获得的最大折扣数：</div>
<div>
<table style="border-collapse: collapse; border: medium none;" cellspacing="0" cellpadding="0">

<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; background: #cccccc 0% 50%; padding-bottom: 0cm; padding-top: 0cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; border: windowtext 1pt solid;">
<div style="margin: 0cm 0cm 7.8pt;">本数</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: 1pt solid; padding-left: 5.4pt; background: #cccccc 0% 50%; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0cm 0cm 7.8pt;">可能的分解本数</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: 1pt solid; padding-left: 5.4pt; background: #cccccc 0% 50%; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0cm 0cm 7.8pt;">对应的折扣</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>对于2-5本，</div>
<div>直接按折扣</div>
<div>购买</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>5%</div>
<div>10%</div>
<div>20%</div>
<div>25%</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>6</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=4+2</div>
<div>=3+3</div>
<div>=2+2+2</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>0.9</div>
<div>0.6</div>
<div>0.3</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>7</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=5+2</div>
<div>=4+3</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>1.35</div>
<div>1.1</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>8</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=5+3</div>
<div>=4+4</div>
<div>=3+3+2</div>
<div>=2+2+2+2</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div><span style="color: blue;">5*25%+3*10%=1.55</span></div>
<div><span style="color: blue;">4*20%+4*20%=1.6</span></div>
<div>0.7</div>
<div>0.4</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>9</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=5+4</div>
<div>=5+2+2</div>
<div>=4+3+2</div>
<div>=3+3+3</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>2.05</div>
<div>1.45</div>
<div>1.2</div>
<div>0.9</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>10</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=5+5</div>
<div>=4+4+2</div>
<div>=4+3+3</div>
<div>=2+2+2+2+2</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>2.5</div>
<div>1.7</div>
<div>1.4</div>
<div>0.5</div>
</td>
</tr>

</table>
</div>
<div style="margin: 0cm 0cm 7.8pt;">表1-2 折扣计算表</div>
<div style="margin: 7.8pt 0cm 15.6pt; text-indent: 14.4pt;">看上面给出的折扣计算表，我们可以简单分析一下。实际上这个反例产生的原因是3本书的折扣数量与4本书的折扣数量差距过大造成的。实际上只要我们将题目稍微改动一下，将三本书的折扣改成15%，得到表1-2所示的折扣，我们就会发现贪心算法奇迹般地生效了！（为清楚起见，我把修改前和修改后的折扣计算结果放到了一张表中）那么如果一开始作者给出的就是三本书15%的折扣的话，从表中就可以看出使用原始的贪心算法所得到的结果是对的，就可能会连带得出贪心算法有效的结论？！<strong>我有点后怕！</strong></div>
<div style="margin: 7.8pt 0cm 15.6pt; text-indent: 14.4pt;">很显然，如果可以应用贪心算法的话，贪心选择不应该局限于某一种折扣数量的设定。而如果《哈利波特》不是5卷而是M卷，折扣表扩大的话，就很可能会产生更多的反例情况。</div>
<div>
<table style="border-collapse: collapse; border: medium none;" cellspacing="0" cellpadding="0">

<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; background: #cccccc 0% 50%; padding-bottom: 0cm; padding-top: 0cm; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; border: windowtext 1pt solid;">
<div style="margin: 0cm 0cm 7.8pt;">本数</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: 1pt solid; padding-left: 5.4pt; background: #cccccc 0% 50%; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0cm 0cm 7.8pt;">可能的分解本数</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: 1pt solid; padding-left: 5.4pt; background: #cccccc 0% 50%; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0cm 0cm 7.8pt;">原始的折扣</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: 1pt solid; padding-left: 5.4pt; background: #cccccc 0% 50%; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0cm 0cm 7.8pt;">新的折扣</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div><span style="color: #ff6600;">对于</span><span style="color: #ff6600;">2-5</span><span style="color: #ff6600;">本，</span></div>
<div><span style="color: #ff6600;">直接按折扣</span></div>
<div><span style="color: #ff6600;">购买</span></div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>5%</div>
<div>10%</div>
<div>20%</div>
<div>25%</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>5%</div>
<div>15%</div>
<div>20%</div>
<div>25%</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>6</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=4+2</div>
<div>=3+3</div>
<div>=2+2+2</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>0.9</div>
<div>0.6</div>
<div>0.3</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>0.9</div>
<div><span style="color: red;">0.9</span></div>
<div>0.3</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>7</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=5+2</div>
<div>=4+3</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>1.35</div>
<div>1.1</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>1.35</div>
<div><span style="color: red;">1.25</span></div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>8</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=5+3</div>
<div>=4+4</div>
<div>=3+3+2</div>
<div>=2+2+2+2</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div><span style="color: blue;">5*25%+3*10%=1.55</span></div>
<div><span style="color: blue;">4*20%+4*20%=1.6</span></div>
<div>0.7</div>
<div>0.4</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div><span style="color: red;">5*25%+3*15%=1.7</span></div>
<div>1.6</div>
<div><span style="color: red;">3*15%*2+2*10%=1.0</span></div>
<div>0.4</div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>9</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=5+4</div>
<div>=5+2+2</div>
<div>=4+3+2</div>
<div>=3+3+3</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>2.05</div>
<div>1.45</div>
<div>1.2</div>
<div>0.9</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>2.05</div>
<div>1.45</div>
<div><span style="color: red;">0.8+0.45+0.1=1.35</span></div>
<div><span style="color: red;">0.45*3=1.35</span></div>
</td>
</tr>
<tr>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; padding-top: 0cm; border-bottom: 1pt solid;">
<div>10</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>=5+5</div>
<div>=4+4+2</div>
<div>=4+3+3</div>
<div>=2+2+2+2+2</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>2.5</div>
<div>1.7</div>
<div>1.4</div>
<div>0.5</div>
</td>
<td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: 1pt solid;">
<div>2.5</div>
<div>1.7</div>
<div><span style="color: red;">1.7</span></div>
<div>0.5</div>
</td>
</tr>

</table>
</div>
<div style="margin: 0cm 0cm 7.8pt;">表1-3与贪心策略相符合的折扣表</div>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 14.4pt;">于是作者想把多余10本的订单分成若干个小于10的订单组，并把每组的最大折扣相加，以得到全局最优解，关于这一点我将在下面进行说明。作者在最后讲述了修改贪心策略的方法，不过我不是太理解，而且其中还有一些错误，最重要的是作者最终也没能证明其正确性，我就不再深究了。</div>
<div style="margin: 7.8pt 0cm 15.6pt 21.25pt; text-indent: -21.25pt;"><strong><span style="font-size: x-large;"><span><span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal;"><font size="5">2</font> </span></span></span><span style="font-size: large;">贪心算法是否适用的分析</span></strong></div>
<div style="margin: 7.8pt 0cm 15.6pt; text-indent: 14.4pt;">贪心算法的适用有两个必要条件，即优化子结构和贪心选择性。第一个性质由于已经证明可以适用动态规划算法，所以优化子结构性质显然成立（假如书中的动态规划递归式成立的话）。现需要证明其贪心选择性，即如何&ldquo;贪心&rdquo;的进行选择。显然每次都查找最大的折扣数进行处理的贪心方法是行不通的，那么是贪心方法真的不行还是我们&ldquo;贪&rdquo;的不正确呢？我们下面就来分析。</div>
<div style="margin: 7.8pt 0cm 15.6pt; text-indent: 14.4pt;">贪心选择性的含义是，一个全局最优解可以通过局部最优选择来达到，换句话说，当考虑作何选择时，我们只考虑对当前问题最佳的选择而不考虑子问题的结果。贪心算法所做的当前选择可能要依赖于已经做出的所有选择，但不依赖于有待于做出的选择或子问题的解。所以，贪心策略通常是自顶向下地，一个一个地做出贪心选择，不断地将给定的问题归约为更小的问题。当然，在此之前我们必须证明在每一步所做的贪心选择最终能产生一个全局最优解，这也正是本题的关键所在。</div>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 14.45pt;">书中解法二给出的分组的思想是可以借鉴的，但是显然犯了方向性的错误。因为贪心算法的关键在于&ldquo;<strong>选择</strong>&rdquo;，即从当前的状态来&ldquo;贪心地&rdquo;从多种子状态中选择一个&ldquo;当前的&rdquo;最优解进行下去，并由其贪心选择性而使最终的解刚好是最优解。既然书中最后采用的还是（经修改后的）贪心算法，就不应该把整体的问题分成若干组来执行。这是因为贪心算法的上一次选择与下一次选择之间是带有连续性的，并不能够将它们拆开处理；而如果要拆开处理之后再将结果相加，就还需要证明拆分是使得结果最优的拆分。所以我们的目标最终还是应该定为寻找如何&ldquo;贪&rdquo;！其实作者的意图是对的，但实际目标应该定为<strong>限制本次选择对于此后选择的影响，或使本次选择的影响仅限于下一次选择，</strong>这也是表格1-1只需要计算到10的原因（两次选择最多选择10本书），但由于下一次选择的影响可能会影响下下次的选择，所以我们不能硬性将这些选择拆开然后再相加，而只能一次一次地完成选择。</div>
<div style="margin: 7.8pt 0cm 15.6pt;"><strong><span style="font-size: large;">2.1特殊情况</span></strong></div>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 14.45pt;">首先，让我们分析一下<span style="text-decoration: underline;">图2-1左图</span>所示的订单，很显然，蓝框所框住的15本书都应该按照5本书的折扣处理。我们之所以&ldquo;敢&rdquo;这么做的原因是这次的处理不会影响到下一次的&ldquo;选择&rdquo;。即如果蓝框的范围再向上扩大一层的话，一次选择之后就会使得最后两列书的数量为0，并导致下次选择时最多只有3本书的折扣可以选择，相当于间接地选择了&ldquo;5+3&rdquo;模式。而如果蓝框的范围如图2-2(左)所示的话，这两次处理我们还可以有&ldquo;4+4&rdquo;模式可供选择，而这才是最佳选择。所以，当我们的选择不会使列数减少的时候，我们可以放心大胆地选择利润最大的那选择法；同样在<span style="text-decoration: underline;">图2-1右图（注意：左右两图并无关联，是两个不同的订单）</span>，由于第五列已经没有了，在蓝框范围内的书籍我们仍然应该按照左图的做法处理，只是这次我们的折扣是4本书的。</div>
<div style="margin: 7.8pt 0cm 15.6pt; text-indent: 14.4pt;">再细想一下，如果我们不选择折扣最大的（即书的数量最多的）那个选择，按照<strong>书中给出的动态规划子问题的定义中的取法：如果取<span>4本书是从前四列取，取3本书从前三列取，依次类推，我们权且称其为&ldquo;<span style="color: red;">最小取法</span>&rdquo;（与书中的&ldquo;最小表示&rdquo;相呼应），</span></strong>我们可以知道，这一次不选择折扣最大只是将折扣最大的选择&ldquo;推后&rdquo;了。因为贪心算法每一步的选择都应该是当前状况下的最优选择，即我们在每一步都应该尽可能多获得折扣，而不应该将折扣&ldquo;推后&rdquo;而导致我们本次的选择并非最佳选择。换句话说，<strong>我们应该保证下一次选择的书的数量不应该比本次选择的数量多</strong>，即我们可以允许两次的选择是5+3或4+4，但绝不能允许3+5出现。作者给出的表1-1也印证了这一点，我们可以看到，<strong>表中所有的拆分都是降序排列的，即下一次可选择的最大数量不会超过本次选择的书的数量</strong>。</div>
<div style="margin: 7.8pt 0cm 15.6pt; text-indent: 14.4pt;">&nbsp;<img src="http://p.blog.csdn.net/images/p_blog_csdn_net/kabini/program-beauty-2-1.PNG" alt="" /></div>
<p style="margin: 0cm 0cm 7.8pt;"></p>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 14.4pt;">例如<span style="text-decoration: underline;">图2-2左图</span>中，如果我们本次选择（最底层）只选择了3本书，那么上一段定义的<strong><span style="color: red;">最小取法</span></strong>，我们得到的子问题应该是F（Y<sub>1</sub>-1，Y<sub>2</sub>-1，Y<sub>3</sub>-1，Y<sub>4</sub>，Y<sub>5</sub>），于是下一次我们仍然可以选择5本书，大于本次所选的三本书，这是不应该发生的。而如果我们选择5本书，下一次只有3本书可以选择，这显然是可以的，但并不是最优的；如果我们选择4+4呢？显然不违反我们刚才定下的规则，而且折扣最大。下面我们的问题就是如何对原始的贪心定义稍作修改，使其能够帮我们挑出最大折扣的选法。</div>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 14.4pt;">在处理掉一些特殊情况之后，我们的订单变为<span style="text-decoration: underline;">图2-2左图</span>所示的情况。而且前面我们定义：<strong>本次选择的书的数量不应该小于下一次可选择的书的最大数量（其中，书的取法按照书中动态规划方法给出的选法来进行）</strong>。也就是说，我们不应该把最大的折扣选择&ldquo;推后&rdquo;执行，而使得本次选择不是当前看起来&ldquo;最优的&rdquo;。其次，这种选取方式也使得本次选择的影响仅限于下一次（即图中红色框中的范围），而不会&ldquo;扩散&rdquo;到下一次选择之后的选择，例如下下次选择。同时，下下次选择也只受下次选择的影响，由此我们成功地阻止了本次选择对整体带来的影响。</div>
<div style="margin: 7.8pt 0cm 15.6pt;"><strong><span style="font-size: large;">2.2修改的贪心算法</span></strong></div>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 14.4pt;">对于<span style="text-decoration: underline;">图2-2左图</span>所示的情况，在满足上述条件的前提下，我们目前有5和4两种选择（当然，如果书的卷数为M&gt;5的话，可能的选择也许会更多），我们如何在不引发贪心反例的情况下获得最大折扣呢？我的答案是<strong>&ldquo;查表&rdquo;。</strong>此时，我们应该查阅表<span>1-2，找到其中折扣数最大的那个最为本次的选择。我们可以看到，因为5+3&lt;4+4，所以我们本次应该选择4本书。我们还需要验证，下一次选择我们还需要选择4本书。此时状况如</span>图2-2右图所示，我们的选择只有4+3，因为如果本次我们选择3本书，下一次我们还可以选择4本书，这与我们的规则不符。所以我们的贪心选择是正确的。其余的书籍我们可以按照上面提到的两种情况加以处理即可。</div>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 14.4pt;"><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/kabini/program-beauty-2-2.PNG" alt="" /></div>
<p style="margin: 0cm 0cm 7.8pt; text-indent: 14.4pt;"></p>
<div style="margin: 0cm 0cm 7.8pt; text-indent: 14.4pt;">经过修改后，贪心算法的空间复杂度变为计算如1-2所示的表格的代价，而修改后的贪心算法的时间复杂度就很直观，应该为我们做出选择的次数（包括一次查表操作），也就是O（Y1）。</div>
<div style="margin: 7.8pt 0cm 15.6pt;"><strong><span style="font-size: large;">3总结</span></strong></div>
<div style="margin: 0cm 0cm 7.8pt;">本问题的修改后的贪心算法的规则是：</div>
<div>1 <strong>本次选择的书的数量不应该小于下一次可选择的书的最大数量（其中，书的取法按照书中动态规划方法给出的选法来进行）</strong>。</div>
<div style="margin: 7.8pt 0cm 15.6pt;"><strong>2 </strong><strong>每一次选择之前都应该查表，选择其中使得近两次折扣数最大的那个作为本次选择（因为我们使得本次选择的影响被控制在两次选择的范围内）。</strong></div>
<div style="margin: 7.8pt 0cm 15.6pt;">而<span style="text-decoration: underline;">图2-1左图</span>中蓝框内的情况最终也可以归结为后面所分析的状况中的一种。即因为下一次只有<span>5可以选择（少于五本将违反规则1），所以本次就选择5本书。此外，当书的卷数变为M(M&gt;5)的时候，表1-2需要的计算的数量也会相应变大。但实际上表1-2可以简化，例如我们看8本书的情况， 3+3+2和2+2+2+2其实都不用考虑，因为按照图2-2左图所示，因为规则1的存在使我们不可能选择3本书。即便是换一个例子，如果我们本次选择3本书、下一次最多也只能选3本书的话，我们就回到了处理图2-2左图蓝框中的情况当中。最后，如果书的卷数为M，则我们的表格的行数只需要为2M即可，</span><strong>因为我们一次选择的影响仅限于本次和下次，所涉及的书的数量不会超过<span>2M个</span></strong>。</div>
<div style="margin: 7.8pt 0cm 15.6pt;"><strong><span style="font-size: x-large;"><font size="5">4《编程之美》本问题勘误</font> </span></strong></div>
<div style="margin: 0cm 0cm 7.8pt;">[1] P33，本数为6的4+2的折扣应该是4*20%+2*5%=0.9而不是1.1</div>
<div style="margin: 0cm 0cm 7.8pt;">[2] P34，最后一段，第2-3行说原始的&ldquo;<strong>贪心策略建议我们买</strong><strong>Y5</strong><strong>本卷五，<span style="color: #ff6600;">Y4-Y5</span></strong><strong>本卷四，Y3-Y4</strong><strong>本卷三，Y2-Y3</strong><strong>本卷二和Y1-Y2</strong><strong>本卷一</strong>&rdquo;，对于订单（2，2，2，1，1），其中前三卷每卷两本，后两卷每卷一本，贪心的规则应该是5+3，即第一次选择应该每卷拿一本才对。<strong>而文中说第四卷拿</strong><strong>Y4-Y5=0</strong><strong>本？</strong>所以这段文字我认为不妥。而且对于这一段后面的内容我也不是太明白，我个人觉得有修改一下的必要。</div>
<div style="margin: 0cm 0cm 7.8pt;">[3] 同样是P34最后一段，最后三行。虽然我对这一段的意思不太了解，但是仍然可以看出一个明显的错误，那就是最后三行所举的例子提到&ldquo;要买3本第一卷，<span style="color: red;">2</span><span style="color: red;">本第二卷</span><span style="color: red;">&hellip;.</span>&rdquo;，而在最后却说&ldquo;经调整后的贪心策略告诉我们应该买三本四卷，<span style="color: red;">三本两卷</span>&hellip;.&rdquo;，前面说第二卷一共就两本，后面却说要买3本第二卷，真不知道这个贪心策略是怎么&ldquo;告诉的&rdquo;。我建议，反正由于书的价格导致订单上的书到底第几卷不重要，就不如干脆不用第几卷，改用第几列更为合适。</div>
<div style="margin: 0cm 0cm 7.8pt;">原博客地址：<a href="http://blog.csdn.net/kabini/archive/2008/04/16/2296943.aspx">http://blog.csdn.net/kabini/archive/2008/04/16/2296943.aspx</a></div><img src="http://www.msdnclub.com/utility/AggView.ashx?ViewObject=7&PostID=171" width="1" height="1">]]></description></item><item><title>《编程之美》电子书样章（二）</title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/07/28/169.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Mon, 28 Jul 2008 09:07:56 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:169</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=169</comments><slash:comments>0</slash:comments><description><![CDATA[<p>博文视点提供《编程之美&mdash;&mdash;微软技术面试心得》第1章第1.3节&ldquo;一摞烙饼的排序&rdquo;电子书，其中包括题目、分析与解法，供大家下载阅读。</p>
<p>下载地址：<a href="http://files.cnblogs.com/bvbook/laobing.pdf"><span style="color: #006666;">http://files.cnblogs.com/bvbook/laobing.pdf</span></a></p>
<p>谢谢大家。</p><img src="http://www.msdnclub.com/utility/AggView.ashx?ViewObject=7&PostID=169" width="1" height="1">]]></description></item><item><title>Nothing replaces hard work——《编程之美》读后感</title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/07/28/168.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Mon, 28 Jul 2008 07:33:36 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:168</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=168</comments><slash:comments>0</slash:comments><description><![CDATA[<p><span style="font-size: x-small;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">看过《编程之美》，想起在西安读大学的时候，见到微软、贝尔这些牛企的面试题总是顶礼膜拜，更有些题目被一届届的传为佳话，比如</span><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;">"</span><span style="font-size: 10pt; color: black; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">井盖为什么是圆的？</span><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;">"</span><span style="font-size: 10pt; color: black; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">。不过自己当时更多的把编程看作是工程，而不是艺术，也坚信成功的软件是工程之美、管理之美、设计之美，自己的精力也更多的关注在开发方法、过程和系统设计上。</span><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;"><br /></span><span style="font-size: 10pt; color: black; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">大学毕业，在工作的这段时间里越来越感觉到代码本身的美感，就像</span><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;"> wordpress </span><span style="font-size: 10pt; color: black; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">网站上的一句话</span><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;"> "code is poetry"</span><span style="font-size: 10pt; color: black; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">。</span><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;"></span></p>
<span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"></p>
<span style="font-size: 10pt; color: black; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">现在读到《编程之美》，让我觉得作者们都是不折不扣的艺术家，他们的创作工具是</span><span style="font-size: 10pt; color: black; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;"> IDE</span><span style="font-size: 10pt; color: black; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">，是键盘，他们的作品是代码。</span><font size="2"><strong><span style="font-size: 13.5pt; color: blue; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">原来望而生畏的面试题现在越看越好玩，越看越上瘾，感谢《编程之美》小组给我的这次思想盛宴。相信无论是在技术一线奋战多年的工程师，还是身在象牙塔的学生，在这本书里都能体会到编程之美。不过要想让别人体会到自己的代码之美，没有捷径，只有沈向洋博士的那句话</span></strong><strong><span style="font-size: 13.5pt; color: blue; font-family: 'Verdana','sans-serif'; mso-bidi-font-family: 宋体;"> "Nothing replaces hard work"</span></strong><strong><span style="font-size: 13.5pt; color: blue; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">。</span></strong></font>
<p class="MsoNormal" style="padding-left: 30px; margin: 0cm 0cm 0pt; text-align: right;"><font style="background-color: #ffffff;" size="2" color="#000000"><strong><span style="font-size: 13.5pt; color: blue; font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana; mso-bidi-font-family: 宋体;">&mdash;&mdash;苏锐</span></strong></font></p>
</span></span></p><img src="http://www.msdnclub.com/utility/AggView.ashx?ViewObject=7&PostID=168" width="1" height="1">]]></description></item><item><title>《编程之美》读书笔记（四）：烙饼问题与搜索树</title><link>http://www.msdnclub.com/u/bvbook/Blog/archive/2008/07/25/166.aspx</link><author>博文视点</author><dc:creator>博文视点</dc:creator><pubDate>Fri, 25 Jul 2008 09:39:16 GMT</pubDate><guid isPermaLink="False">b46801a8-160b-4363-bfda-85004160ab27:Weblog:166</guid><comments>http://www.msdnclub.com/u/Blog/ShortLink.aspx?UserDomainName=bvbook&amp;PostID=166</comments><slash:comments>0</slash:comments><description><![CDATA[<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt; text-indent: 21pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm; mso-layout-grid-align: none;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-size: x-small;">作者：</span><a class="null" title="薛笛博客" href="http://blog.csdn.net/kabini"><span style="font-size: x-small;">薛笛</span></a></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt; text-indent: 21pt; line-height: 150%; text-align: left; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm; mso-layout-grid-align: none;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">前面已经写了一些关于烙饼问题的简单分析，但因为那天太累有些意犹未尽，今天再充实一些内容那这个问题研究透。我想，通过这篇文章，我们就可以把这一类问题搞懂。再遇到优化问题，如果我们想不到别的办法，就可以采用搜索树算法来解决，至少我们不至于拿不出解决方案。前面我们已经知道，关于一摞烙饼的排序问题我们可以采用递归的方式来完成。其间我们要做的是尽量调整</span><span><font face="Times New Roman">UpperBound</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">和</span><span><font face="Times New Roman">LowerBound</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，已减少运算次数。对于这种方法，在算法课中我们应该称之为：</span><span><font face="Times New Roman">Tree Searching Strategy</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">。即整个解空间为一棵搜索树，我们按照一定的策略遍历解空间，并寻找最优解。一旦找到比当前最优解更好的解，就用它替换当前最优解，并用它来进行&ldquo;剪枝&rdquo;操作来加速求解过程。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt; text-indent: 21pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm; mso-layout-grid-align: none;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">书中给出的解法就是采用深度优先的方式来遍历这棵搜索树，例如要排序</span><span><font face="Times New Roman">[4,2,1,3]</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，最大反转次数不应该超过</span><span><font face="Times New Roman">(4-1)*2=6</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">次，所以搜索树的深度也不应大于</span><span><font face="Times New Roman">6</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，搜索树如下图所示：</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt; text-indent: 21pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm;" align="left"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-size: x-small;"><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/kabini/Program3-searchTree.JPG" alt="" /></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt; text-indent: 21pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">这里只列到第三层，其中被画斜线的方块由于和上层的某一节点的状态重复而无需再扩展下去（即便扩展也不可能比有相同状态的上层节点的代价少）。我们可以看到在右子树中的一个分支，只需要用</span><span><font face="Times New Roman">3</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">次反转即可完成，我们的目标是如何更为快速有效的找到这一分支。直观上我们可以看到：基本的搜索方法要先从左子树开始，所以要找到本例最佳的方案的代价是很高的（利用书中的算法需要查找</span><span><font face="Times New Roman">292</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">次）。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt; text-indent: 21pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-size: x-small;">既然要遍历搜索树，就有广度优先和深度优先之分，可以分别用栈和队列来实现（当然也可以用递归的方法）。那么如何能更有效地解决问题呢？我们主要考虑一下几种方法：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; text-indent: -36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt;"><span style="font-size: x-small;"><span style="mso-bidi-font-family: 宋体;"><span style="mso-list: Ignore;"><font face="Times New Roman">（1）<span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">爬山法</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">该方法是在深度优先的搜索过程中使用贪心方法确定搜索方向，它实际上是一种深度优先搜索策略。爬山法采用启发式侧读来排序节点的扩展顺序，其关键点就在于测度函数</span><span><font face="Times New Roman">f(n)</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">的定义。我们来看一下如何为上例定制代价函数</span><span><font face="Times New Roman">f(n)</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，以快速找到右子树中最好的那个分支（很像贪心算法，呵呵）。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">我们看到在</span><span><font face="Times New Roman">[1,2,4,3]</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">中，</span><span><font face="Times New Roman">[1,2,3]</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">已经相对有序，而</span><span><font face="Times New Roman">[4]</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">位与他们之间，要想另整体有序，需要</span><span><font face="Times New Roman">4</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">次反转；而</span><span><font face="Times New Roman">[3,1,2,4]</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">中，由于</span><span><font face="Times New Roman">[4]</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">已经就位，剩下的数变成了长度为</span><span><font face="Times New Roman">3</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">的子队列，而子队列中</span><span><font face="Times New Roman">[1,2]</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">有序，令其全体有序只需要</span><span><font face="Times New Roman">2</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">次反转。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-size: x-small;">所以我们的代价函数应该如下定义：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt;"><span style="font-size: x-small;"><span><font face="Times New Roman">1 </font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">从当前状态的最后一个饼开始搜索，如果该饼在其应该在的位置（中间断开不算），则跳过；</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt;"><span style="font-size: x-small;"><span><font face="Times New Roman">2 </font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">自后向前的搜索过程中，如果碰到两个数不相邻的情况，就</span><span><font face="Times New Roman">+1</font></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-size: x-small;">这样我们就可以在本例中迅速找到最优分枝。因为在树的第一层</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-size: x-small;"><span><font face="Times New Roman">f(2,4,1,3)=3</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，</span><span><font face="Times New Roman">f(1,2,4,3)=2</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，</span><span><font face="Times New Roman">f(3,1,2,4)=1</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，所以我们选择</span><span><font face="Times New Roman">[3,1,2,4]</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">那一枝，而在</span><span><font face="Times New Roman">[3,1,2,4]</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">的下一层：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-size: x-small;"><span><font face="Times New Roman">f(1,3,2,4)=2</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，</span><span><font face="Times New Roman">f(2,1,3,4)=1</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，</span><span><font face="Times New Roman">f(4,2,1,3)=2</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，所以我们又找到了最佳的路径。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">上面方法看似不错，但是数字比较多的时候呢？我们来看书中给出的</span><span><font face="Times New Roman">10</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">个数的例子：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-size: 10pt; color: black; line-height: 150%; font-family: 'Courier New'; mso-font-kerning: 0pt;">[3,2,1,6,5,4,9,8,7,0]</span><span style="font-size: 10pt; color: black; line-height: 150%; font-family: 宋体; mso-hansi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-font-kerning: 0pt;">，</span><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">程序给出的最佳翻转序列为</span><span><font face="Times New Roman">{</font></span><span style="font-size: 10pt; color: black; line-height: 150%; font-family: 'Courier New'; mso-font-kerning: 0pt;"> 4,8,6,8,4,9</span><span><font face="Times New Roman">}</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">（从</span><span><font face="Times New Roman">0</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">开始算起）</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-size: x-small;">那么，对于搜索树的第一层，按照上面的算法我计算的结果如下：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; text-align: left; mso-layout-grid-align: none;" align="left"><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;">f(2,3,1,6,5,4,9,8,7,0)=4</span><span style="font-size: 10pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;" align="left"><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;</span>f(1,2,3,6,5,4,9,8,7,0)=3</span><span style="font-size: 10pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;" align="left"><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;</span>f(6,1,2,3,5,4,9,8,7,0)=4</span><span style="font-size: 10pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;" align="left"><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;</span>f(5,6,1,2,3,4,9,8,7,0)=3</span><span style="font-size: 10pt; font-family: 'Courier New'; mso-font-kerning: 0pt;"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;" align="left"><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;</span>f(</span><span style="font-size: 10pt; color: #ff6600; font-family: 'Courier New'; mso-font-kerning: 0pt;">4,5,6,1,2,3,9,8,7,0</span><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;">)</span><span style="font-size: 10pt; color: #ff6600; font-family: 'Courier New'; mso-font-kerning: 0pt;">=3</span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;" align="left"><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;</span>f(9,4,5,6,1,2,3,8,7,0)=4</span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-layout-grid-align: none;" align="left"><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;"><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-tab-count: 1;">&nbsp;&nbsp;&nbsp;</span>f(8,9,4,5,6,1,2,3,7,0)=4</span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; text-align: left; mso-layout-grid-align: none;" align="left"><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;">f(7,8,9,4,5,6,1,2,3,0)=3</span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; text-align: left; mso-layout-grid-align: none;" align="left"><span style="font-size: 10pt; color: #3f7f5f; font-family: 'Courier New'; mso-font-kerning: 0pt;">f(0,7,8,9,4,5,6,1,2,3)=3</span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">我们看到有</span><span><font face="Times New Roman">4</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">个分支的结果和最佳结果相同，也就是说，我们目前的代价函数还不够&ldquo;一击致命&rdquo;，但是这已经比书中的结果要好一些，起码我们能更快地找到最佳方案，这使得我们在此后的剪枝过程更加高效。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; text-indent: 6pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 3.43gd;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-size: x-small;">爬山法的伪代码如下：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt;"><span style="font-size: x-small;"><span><font face="Times New Roman">1 </font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">构造由根组成的单元素栈</span><span><font face="Times New Roman">S</font></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt;"><span style="font-size: x-small;"><span><font face="Times New Roman">2 IF Top(s)</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">是目标节点</span><span><font face="Times New Roman"> THEN </font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">停止；</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt;"><span><span style="font-size: x-small; font-family: Times New Roman;">3 Pop(s);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt;"><span style="font-size: x-small;"><span><font face="Times New Roman">4 S</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">的子节点按照启发式测度，由小到大的顺序压入</span><span><font face="Times New Roman">S</font></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 36pt;"><span style="font-size: x-small;"><span><font face="Times New Roman">5 IF </font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">栈空</span><span><font face="Times New Roman"> Then </font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">失败</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: x-small;"><span><font face="Times New Roman">Else </font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">返回</span><span><font face="Times New Roman">2</font></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 42pt;"><span><span style="font-size: x-small; font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: x-small;"><span><span style="mso-tab-count: 2;"><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">如果有时间我会把爬山法解决的烙饼问题贴在后面。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; text-indent: -36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt;"><span style="font-size: x-small;"><font face="Times New Roman"><span style="mso-bidi-font-family: 宋体;"><span style="mso-list: Ignore;">（2）<span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>Best-First</span></font><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">搜索策略</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';"><span style="font-size: x-small;">最佳优先搜索策略结合了深度优先和广度优先二者的优点，它采取的策略是根据评价函数，在目前产生的所有节点中选择具有最小代价值的节点进行扩展。该策略具有全局优化的观念，而爬山法则只具有局部优化的能力。具体用小根堆来实现搜索树就可以了，这里不再赘述。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; text-indent: -36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt;"><span style="font-size: x-small;"><font face="Times New Roman"><span style="mso-bidi-font-family: 宋体;"><span style="mso-list: Ignore;">（3）<span style="font: 7pt 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>A*</span></font><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">算法</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">如果我们把下棋比喻成解决问题，则爬山法和</span><span><font face="Times New Roman">Best-First</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">算法就是两个只能&ldquo;看&rdquo;未来一步棋的玩家。而</span><span><font face="Times New Roman">A*</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">算法则至少能够&ldquo;看&rdquo;到未来的两步棋。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 36pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 36.0pt;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">我们知道，搜索树的每一个节点的代价</span><span><font face="Times New Roman">f*(n)=g(n)+h*(n)</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">。其中，</span><span><font face="Times New Roman">g(n)</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">为从根节点到节点</span><span><font face="Times New Roman">n</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">的代价，这个值我们是可求的；</span><span><font face="Times New Roman">h*(n)</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">则是从</span><span><font face="Times New Roman">n</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">节点到目标节点的代价，这个值我们是无法实际算出的，只能进行估计。我们可以用下一层节点代价的最小者来替代</span><span><font face="Times New Roman">h*(n)</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，这也就是&ldquo;看&rdquo;了两步棋。可以证明，如果</span><span><font face="Times New Roman">A*</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">算法找到了一个解，那它一定是优化解。</span><span><font face="Times New Roman">A*</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">算法的描述如下：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 54pt; text-indent: -18pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 54.0pt; mso-list: l1 level1 lfo2; tab-stops: list 54.0pt;"><span style="font-size: x-small;"><span style="mso-fareast-font-family: 'Times New Roman';"><span style="mso-list: Ignore;"><font face="Times New Roman">1．<span style="font: 7pt 'Times New Roman';">&nbsp; </span></font></span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">使用</span><span><font face="Times New Roman">BestFirst</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">搜索树</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 54pt; text-indent: -18pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 54.0pt; mso-list: l1 level1 lfo2; tab-stops: list 54.0pt;"><span style="font-size: x-small;"><span style="mso-fareast-font-family: 'Times New Roman';"><span style="mso-list: Ignore;"><font face="Times New Roman">2．<span style="font: 7pt 'Times New Roman';">&nbsp; </span></font></span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">按照上面所述对下层点</span><span><font face="Times New Roman">n</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">进行计算获得</span><span><font face="Times New Roman">f*(n)</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">的估计值</span><span><font face="Times New Roman">f(n)</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，并取其最小者进行扩展。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt 54pt; text-indent: -18pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 54.0pt; mso-list: l1 level1 lfo2; tab-stops: list 54.0pt;"><span style="font-size: x-small;"><span style="mso-fareast-font-family: 'Times New Roman';"><span style="mso-list: Ignore;"><font face="Times New Roman">3．<span style="font: 7pt 'Times New Roman';">&nbsp; </span></font></span></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">若找到目标节点，则算法停止，返回优化解</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 7.8pt; line-height: 150%; mso-para-margin-top: 0cm; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm;"><span style="font-size: x-small;"><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">总结：归根到底，烙饼问题之所以难于在多项式时间内解决的关键就在于我们无法为搜索树中的每一条边设定一个合理的权值。在这里，每条边的权值都是</span><span><font face="Times New Roman">1</font></span><span style="font-family: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman';">，因为从上一个状态节点到下一个状态节点之需要一次翻转。所以我们不能简单地把每个节点的代价定义为翻转次数，而应该根据其