算法设计技巧与分析答案
❶ 绠楁硶璁捐℃妧宸т笌鍒嗘瀽锲句功鐩褰
杩欐湰涔︿互娣卞叆娴呭嚭镄勬柟寮忔帰璁ㄤ简绠楁硶璁捐$殑鎶宸т笌鍒嗘瀽锛屽垎涓轰笁涓涓昏侀儴鍒:
- 锘烘湰姒傚康鍜岀畻娉曞煎紩</
- 绗1绔</: 鐞呜В绠楁硶鍒嗘瀽镄勫熀纭姒傚康锛屼负钖庣画娣卞叆瀛︿範濂犲畾锘虹煶銆
- 绗2绔</: 鎻愪緵蹇呰佺殑鏁板﹂勫囩煡璇嗭纴甯锷╄昏呮帉鎻$畻娉曡儗钖庣殑鏁板﹀师鐞嗐
- 绗3绔</: 鎺㈣ㄦ暟鎹缁撴瀯锛岃繖鏄绠楁硶璁捐$殑镙稿绩锛岀悊瑙f暟鎹缁撴瀯瀵逛紭鍖栫畻娉曡呖鍏抽吨瑕併
- 绗4绔</: 浠嬬粛鍫嗗拰涓岖浉浜ら泦鏁版嵁缁撴瀯锛岃繖涓や釜涓婚桦湪璁稿氱畻娉曚腑镓婕斿叧阌瑙掕壊銆
- 锘轰簬阃掑綊镄勬妧链</
- 绗5绔</: 褰掔撼娉曟槸阃掑綊镄勫熀纭锛屽︿範杩欎竴绔犲皢链夊姪浜庣悊瑙i掑綊绠楁硶镄勮捐°
- 绗6绔</: 鍒嗘不绛栫暐鏄瑙e喅澶嶆潅闂棰樼殑链夋晥镓嬫碉纴娣卞叆镰旂┒杩欎竴绔犳湁锷╀簬浼桦寲绠楁硶銆
- 绗7绔</: 锷ㄦ佽勫垝锛岃В鍐冲氶桩娈靛喅绛栭梾棰樼殑甯哥敤宸ュ叿锛屽湪姝ょ珷涓浣犱细瀛︿範鍒板备綍杩愮敤銆
- 链鍏埚壊鎶链</
- 绗8绔</: 璐蹇幂畻娉曪纴阃氲繃灞閮ㄦ渶浼橀夋嫨杈惧埌鍏ㄥ眬链浼桡纴鏄杩欑被鎶链镄勫叆闂ㄤ粙缁嶃
- 绗9-11绔</: 浠庡浘镄勯亶铡嗗埌NP瀹屽叏闂棰桡纴娣卞叆鐞呜В璁$畻澶嶆潅镐х悊璁猴纴涓轰綘鎻绀虹畻娉曡捐$殑杈圭晫銆
- 绗12-13绔</: 涓嬬晫鍜屽洖婧娉曪纴鎺㈢┒绠楁硶鏁堢巼镄勬瀬闄愬拰绛栫暐璋冩暣镄勭瓥鐣ャ
- 绗14-16绔</: 闅忔満绠楁硶鍜岃繎浼肩畻娉曪纴闱㈠瑰嶆潅闂棰樻椂镄勭伒娲诲簲瀵圭瓥鐣ャ
- 绗17-18绔</: 缃戠粶娴佸拰鍖归厤锛屽叧阌镄勫浘璁烘傚康鍦ㄥ疄闄呴梾棰树腑镄勫簲鐢ㄥ疄渚嬨
- 绗19绔</: Voronoi锲捐В锛屽嚑浣旷┖闂翠腑镄勭畻娉曞簲鐢锛岀洿瑙傚𪾢绀虹畻娉曞湪瀹为檯鍦烘櫙涓镄勮繍浣溿
❷ 算法设计技巧与分析里第一章的题目求解答
n!/2^n+n^(n/2) =Θ(n!/2^n)
因为
所以
n!/2^n >> n^(n/2)
❸ 请教高人 递归算法编写思路技巧
一个子程序(过程或函数)的定义中又直接或间接地调用该子程序本身,称为递归。递归是一种非常有用的程序设计方法。用递归算法编写的程序结构清晰,具有很好的可读性。递归算法的基本思想是:把规模大的、较难解决的问题变成规模较小的、易解决的同一问题。规模较小的问题又变成规模更小的问题,并且小到一定程度可以直接得出它的解,从而得到原来问题的解。
利用递归算法解题,首先要对问题的以下三个方面进行分析:
一、决定问题规模的参数。需要用递归算法解决的问题,其规模通常都是比较大的,在问题中决定规模大小(或问题复杂程度)的量有哪些?把它们找出来。
二、问题的边界条件及边界值。在什么情况下可以直接得出问题的解?这就是问题的边界条件及边界值。
三、解决问题的通式。把规模大的、较难解决的问题变成规模较小、易解决的同一问题,需要通过哪些步骤或等式来实现?这是解决递归问题的难点。把这些步骤或等式确定下来。
把以上三个方面分析好之后,就可以在子程序中定义递归调用。其一般格式为:
if 边界条件 1 成立 then
赋予边界值 1
【 elseif 边界条件 2 成立 then
赋予边界值 2
┇ 】
else
调用解决问题的通式
endif
例 1 : 计算勒让德多项式的值
x 、 n 由键盘输入。
分析: 当 n = 0 或 n = 1 时,多项式的值都可以直接求出来,只是当 n > 1 时,才使问题变得复杂,决定问题复杂程度的参数是 n 。根据题目提供的已知条件,我们也很容易发现,问题的边界条件及边界值有两个,分别是:当 n = 0 时 P n (x) = 1 和当 n = 1 时 P n (x) = x 。解决问题的通式是:
P n (x) = ((2n - 1)P n - 1 (x) - (n - 1)P n - 2 (x)) / n 。
接下来按照上面介绍的一般格式定义递归子程序。
function Pnx(n as integer)
if n = 0 then
Pnx = 1
elseif n = 1 then
Pnx = x
else
Pnx = ((2*n - 1)*Pnx(n - 1) - (n - 1)*Pnx(n - 2)) / n
endif
end function
例 2 : Hanoi 塔问题:传说印度教的主神梵天创造世界时,在印度北部佛教圣地贝拿勒斯圣庙里,安放了一块黄铜板,板上插着三根宝石针,在其中一根宝石针上,自下而上地放着由大到小的 64 个金盘。这就是所谓的梵塔( Hanoi ),如图。梵天要求僧侣们坚持不渝地按下面的规则把 64 个盘子移到另一根针上:
(1) 一次只能移一个盘子;
(2) 盘子只许在三根针上存放;
(3) 永远不许大盘压小盘。
梵天宣称,当把他创造世界之时所安放的 64 个盘子全部移到另一根针上时,世界将在一声霹雳声中毁灭。那时,他的虔诚的信徒都可以升天。
要求设计一个程序输出盘子的移动过程。
分析: 为了使问题更具有普遍性,设共有 n 个金盘,并且将金盘由小到大依次编号为 1 , 2 ,…, n 。要把放在 s(source) 针上的 n 个金盘移到目的针 o(objective) 上,当只有一个金盘,即 n = 1 时,问题是比较简单的,只要将编号为 1 的金盘从 s 针上直接移至 o 针上即可。可定义过程 move(s,1,o) 来实现。只是当 n>1 时,才使问题变得复杂。决定问题规模的参数是金盘的个数 n ;问题的边界条件及边界值是:当 n = 1 时, move(s,1,o) 。
当金盘不止一个时,可以把最上面的 n - 1 个金盘看作一个整体。这样 n 个金盘就分成了两个部分:上面 n - 1 个金盘和最下面的编号为 n 的金盘。移动金盘的问题就可以分成下面三个子问题(三个步骤):
(1) 借助 o 针,将 n - 1 个金盘(依照上述法则)从 s 针移至 i(indirect) 针上;
(2) 将编号为 n 的金盘直接从 s 针移至 o 针上;
(3) 借助 s 针,将 i 针上的 n - 1 个金盘(依照上述法则)移至 o 针上。如图
其中第二步只移动一个金盘,很容易解决。第一、第三步虽然不能直接解决,但我们已经把移动 n 个金盘的问题变成了移动 n - 1 个金盘的问题,问题的规模变小了。如果再把第一、第三步分别分成类似的三个子问题,移动 n - 1 个金盘的问题还可以变成移动 n - 2 个金盘的问题,同样可变成移动 n - 3 ,…, 1 个金盘的问题,从而将整个问题加以解决。
这三个步骤就是解决问题的通式,可以以过程的形式把它们定义下来:
hanoi(n - 1,s,o,i)
move(s,n,o)
hanoi(n - 1,i,s,o)
参考程序如下:
declare sub hanoi(n,s,i,o)
declare sub move(s,n,o)
input "How many disks?",n
s = 1
i = 2
o = 3
call hanoi(n,s,i,o)
end
sub hanoi(n,s,i,o)
rem 递归子程序
if n = 1 then
call move(s,1,o)
else
call hanoi(n - 1,s,o,i)
call move(s,n,o)
call hanoi(n - 1,i,s,o)
endif
end sub
sub move(s,n,o)
print "move disk";n;
print "from";s;"to";o
end sub