C++经典问题算法分析分解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C++经典问题算法分析分解
一、百钱买百鸡问题(枚举算法)
★算法分析:1、对百钱买百鸡问题的所有结果进行逐一统计验证(枚举验证)。
2、公鸡最多只能买20只,母鸡最多只能买33只,小鸡最多只能
买300只。
3、用for循环进行逐一验证
4、对小鸡的费用应用x/3代替x*(1/3),因为1/3在整型变量下
的值为0。
5、需保证小鸡的数量是3的倍数,即x%3==0。
★源代码:
图1-1
★执行结果:
图1-2
二、填写运算符问题(枚举算法)★算法分析:1、5个数字需要填入4个运算符。
2、每两个数字之间有4种运算符可以选择。
3、当运算符中填入除号时,右边的被除数不能为0.
4、乘除的优先级大于加减的优先级。
5、可以用循环的方法逐一填入各种运算符。
★源代码:
图2-1
三、汉诺塔问题(递归算法)
★算法分析:1、汉诺塔问题可以运用递归算法解决。
2、递归是函数本身调用直接或者间接调用自己的方法。
3、在汉诺塔问题中需要的步骤数是2^n-1。
4、汉诺塔问题步骤解析:
(1)把1座上(n-1)个盘子借助3座移动到2座。
(2)把1座上的第n个盘子移动到3座。
(3)把2座上的(n-1)个盘子借助1座移动到3座。
(4)我们假设用h(n,a,b,c)表示把1座n个盘子借助2 座移动到3座。
由此可得出结论:(1)上是h(n,1,3,2), (2)上是(n-1,2,1,3)★源代码:
图3-1 ★执行结果:
图3-2 ★形象示例:
A B C
图3-3
★故事缘由:
据说古代有一个梵塔,塔内有3个座A、B、C。
A座上有64个圆盘,盘子大小不等,大的在下,小的在上。
有一个和尚想把这64个盘子从A座移动到C 座,但每次只能移动一个圆盘,并在移动过程中始终保持大盘在下,小盘在上。
在移动过程中只能利用B座。
现在需要写出移动的步骤。
这就是汉诺塔问题。
当时这个和尚觉得很难,于是他想,要是有一个人能把前面的63个圆盘移动到B座,自己再把最后一个圆盘移动到C座,那就简单了。
所以他找了另一个和尚来做这件事。
但是另一个和尚也觉得很难,于是又找来了第三个和尚把B 座上的前62个圆盘移动到A座上,自己再把第63个盘子移动到C座。
一次类推,解决汉诺塔问题,一共有64个和尚参与了这项题目。
即是如此,不难看出,每个和尚所做的事是一样的,这就是说解决汉诺塔问题有一种简单而高效地方法,那就是递归调用。
所谓递归调用,就是函数本身直接或间接的调用自己的方法。
递归算法,也是九大经典算法之一。
但是当时没有那么多和尚来完成这件事,确切的说,只能有他自己一个和尚来完成这件事,于是他想起了一位美国学者所发现的一种非常简单的方法。
首先把3个座排列成品字形,如果圆盘的数字是偶数,就按顺时针方向依次排列成A、
B、C。
如果圆盘的数量是奇数是,就按顺时针排列成A、
C、B。
开始时按顺时针方向把第1个圆盘从现在的塔上移动到下一个座,当圆盘数目为偶数时,若圆盘在A上,则把它移动到B座。
若圆盘在B座,则把它移动到C座,若圆盘在C座,则把它移动到A 座。
接着,把另外两座上可以移动的圆盘移动到新的座上。
最后反复进行上面所述的两个步骤,最后就能完成汉诺塔问题。
其实这种方法很简单,就是按照一定的规则向一个方向移动。
例如当圆盘的数量为3时,其移动方向是A-C、A-B、C-B、A-C、B-A、B-C、A-C。
其实这也是汉诺塔问题的非递归算法。
四、阶乘问题(递归算法)
★算法分析:1、阶乘(factorial)是基斯顿·卡曼于1808年发明的运算符号。
2、阶乘可用自身调用自身的递归调用方法解决。
★源代码:
图4-1
★执行结果:
图4-2
五、水仙花数问题
★算法分析:1、所谓水仙花数,就是一个三位数,其各位数字立方和等于该数本身。
例如153就是一个水仙花数。
2、关于求一个三位数的各个位数的问题。
百位数可以直接用该数
除以100解决,因为该数是一个整型变量,其结果也必定是整
型数字,即百位数。
同理,十位数可以用先除10在除10取余
数的方式解决。
个位数直接除10取余数。
3、关于立方的计算,可以直接三个数相乘,也可以调用cmath
库函数进行求解。
★源代码1:
图5-1
★执行结果1:
图5-2
图5-3 ★源代码2:
图6-1 ★执行结果2:
图6-2
六、最大公约数与最小公倍数问题
★算法分析:1、计算两个数的最大公约数比较简单的方法是从两
个数较小的那个数字中开始依次递减,得到的这两个数中第一个公因子即为
所求的最大公约数。
2、计算两个数的最小公约数比较简单的方法是从两个数中较大的
那个数字开始一次加1,得到的第一个公倍数就是两数的最小
公倍数。
3、如果i为a和b的公因数,那么一定满足a%i=0且b%i=0。
所以在算法优化中只需要i从min(a,b)开始依次递减1,,并逐个判断i是不是a和b的公因数,这样得到的第一个公因
数就是其最大公约数。
4、最小公倍数的求解与3一致。
5、跳出一重循环可以在循环体判断条件中添加break语句。
★源代码:
图7-1
★执行结果:
图7-2
七、哥德巴赫猜想问题
★算法分析:1、所谓的哥德巴赫猜想是指每一个大于2的偶数都
可以表示成两个素数之和。
我国数学家陈景润曾经作出重要的贡献。
2、不可能对所有偶数进行举例(因为程序必须是有穷的,而偶数
是无穷的)。
3、判断一个偶数a是不是可以表示成两个素数的和是本算法的核
心。
一个正偶数a一定可以表示成为a/2种正整数相加的形式。
因为a=1+(a-1)=2+(a-2)=3+(a-3)=……a/2+(a-a/2)共
a/2种形式。
所以在这a/2种形式中只要有一种满足两数皆是
素数时即可证明哥德巴赫猜想的正确性。
★伪代码描述:
算法:验证哥德巴赫猜想的正确性
输入:一个数i
i ?
Repeat:
If i是素数and a-i是素数
Then 设置标志,跳出循环
Endif
I<-i+1
Until i>a/2
Else a不满足哥德巴赫猜想
End loop
End
★源代码:
图8-1 图8-2
八、完全数问题
★算法分析:1、完全数是满足所有的真因子(除自身外的约数)的和等于它本身。
例如6是完全数,即6=1+2+3。
2、判断完全数,需要找出数的所有约数,约数是所求数能被除尽
的所有数。
所以只要找出所有约数即可。
3、完全数的性质:
(1)能写成连续自然数之和。
例如6=1+2+3。
(2)全部因数的倒数和为2。
例如1+1/2+3/1+1/6=2。
(3)除6以外的完全数能表示成连续奇次方立方之和。
例如
28=1^3+3^3。
(4)可以表示成2的一些连续正整次幂之和。
例如28 = 2^2
+ 2^3+2^4。
(5)完全数全部以6或8结尾。
(6)除6以外的完全数,把它的各个位数相加,直到变成个
位数,那么这个个位数一定是1。
即除6以外的完全数,
被9除后都是余1。
例如496,4+9+6=19,
1+9=10,1+0=1。
(7)数学家欧几里得推算出来的完全数获得公式:如果2^p-1 为质数,那么(2^p-1)×2^(p-1)就是一个完全数。
当
2^p-1是质数时,称梅森素数。
★源代码:
图9-1 ★执行结果:
图9-2。