|
楼主 |
发表于 2014-8-4 11:10
|
显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用 · 内置多项VBA编程加强工具 ★ 免费下载 ★ ★ 使用手册★
本帖最后由 delete_007 于 2014-8-4 14:36 编辑
三、普遍问题求解
看完上述隔一杀一问题之后,大家肯定都有一个想法:对于更一般的约瑟夫问题,是否也能得出相似的结论呢?答案是否定的,当m>2时,没有相似的规律。下面来探讨一般的约瑟夫问题。
可以用程序来求解约瑟夫问题,但要模拟整个游戏过程,程序也是比较繁杂,而且相当费时。为了追求效率,就要打破常规,实施一点数学策略。
3.1 约瑟夫问题的普适思路
我们知道第一个被淘汰的人(编号为MOD(m-1,n)+1)出列之后,剩下的n-1个人组成新的约瑟夫环,以编号为k=MOD(m,n)+1的人开始。(此处使用MOD是应对m>=n的情况)
1,2,3,4,……,m-2,m-1,m,m+1,m+2,……,n
m被淘汰之后:
k,k+1,k+2,k+3,……,n-1(其中k对应m+1,并且从1开始计数,这就是总人数为n-1的约瑟夫问题)
假设我们知道n-1人的约瑟夫问题的胜利者编号为f(n-1),那么还原为n人约瑟夫问题,其胜利者就是MOD(f(n-1)+m-1,n)+1。
这是一个递推公式,要求f(n),则需先求f(n-1),要求f(n-1),则需先求f(n-2),所以只要知道f(1)就可以求得任意f(n).
显然f(1)=1
f(n)=MOD(f(n-1)+m-1,n)+1, (n>1)
可以从正向来理解上述公式,假设已知n,m的约瑟夫问题的胜利者编号为f(n),那么如何求f(n+1)呢?
对于n+1人的约瑟夫问题,只需要淘汰一人,就可以变成n人的情形。淘汰的第一个是谁呢?当然是第一个报到m的人,然后m+1又从1开始报数。由于已知f(n),那么还原回最初编号即为f(n)+m,又f(n)+m可能已大于n+1,原来序列中无此编号,由于报数是按环形进行,大于n+1的号,也就是MOD(f(n)+m-1,n+1)+1。
3.2 迭代公式求解
由于普适公式是递推公式,并不像隔一杀问题有最终公式表达式,所以启用迭代计算,才能得出正确结果。
下面来看如何在EXCEL中使用迭代计算求解约瑟夫问题:
首先分别在单元格中录入n,m的值,另外还需要设置一个控制迭代的辅助单元格。
如上图,需要在C4,C5中设置公式:
C4迭代参数用于产生1,2,……,100的参数序列,且F9自动重算不影响结果。于是有:
=MOD(IF(C2="",,C4+1)-1,100)+1
C5则是根据3.1节递推公式写成:
=IF(C2="","",IF(C4=1,1,IF(C4>C2,C5,MOD(C5+C3-1,C4)+1)))
即当C4=1时,C5=1,相当于f(1)=1
而当2<=C4<=n=C2时,C5=MOD(C5+C3-1,C4)+1,这是递推公式f(n)=MOD(f(n-1)+m-1,n)+1的体现
当C4>n=C2时,保持C5值不变即可。
详情见附件:
约瑟夫问题之迭代解法.rar
(9.23 KB, 下载次数: 36)
从公式可以看出,无论计算n是多少的情况,都需要迭代100次。这实际上还可以进一步提升效率,通过VBA代码设置迭代次数为n,这样就不会有多余的计算。
公式有优化:C4 =IF(C2="","",MOD(N(C4),C2)+1)
产生1,2,……,n的自然数序列。
C5 =IF(C2="","",IF(C4=1,1,MOD(C5+C3-1,C4)+1))
因为此时C4已不可能大于C2,所以迭代公式可以少一层判断。
设置迭代次数的代码见附件:
约瑟夫问题之迭代解法(优化).rar
(10.08 KB, 下载次数: 50)
(注意:如打开附件弹出循环引用提示框,请直接关闭对话框或点击“取消”以继续。)
|
|