Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 2607|回复: 7

[已解决]VBA编写递归分鱼

[复制链接]
发表于 2016-5-1 13:06 | 显示全部楼层 |阅读模式
VBA编写递归分鱼


最佳答案
2016-5-1 17:42
Sub 求鱼()
Call 最小整数鱼(5, 1)
End Sub
Function countFish(ByVal PNumber As Long, ByVal SYCount As Long, ByVal fishNumber As Long)
Select Case SYCount
  Case PNumber '总人数。
     countFish = fishNumber * PNumber + 1
  Case Else '未达到总人数。继续递归。
     countFish = (countFish(PNumber, SYCount + 1, fishNumber) * PNumber) / (PNumber - 1) + 1
End Select
End Function
Function 最小整数鱼(ByVal PNumber As Long, ByVal SYCount As Long)
Do
m = m + 1
最小整数鱼 = countFish(PNumber, SYCount, m)
Loop Until 最小整数鱼 = Int(最小整数鱼)
Debug.Print PNumber & "人至少捕捞到" & 最小整数鱼 & "条鱼"
Debug.Print "第1人至少看到" & 最小整数鱼 & "条鱼"
For i = 2 To 5
s = Int(最小整数鱼 / PNumber) * (PNumber - 1)
Debug.Print "第" & i & "人至少看到" & s & "条鱼"
最小整数鱼 = s
Next i
End Function

VBA编写递归分鱼.jpg
发表于 2016-5-1 17:38 | 显示全部楼层
  1. Sub aa()
  2. MsgBox fy(5)
  3. End Sub
  4. Function fy(n)
  5. If n = 1 Then
  6.     fy = 16
  7. Else
  8.    fy = fy(n - 1) + 20
  9. End If
  10. End Function
复制代码
回复

使用道具 举报

发表于 2016-5-1 17:42 | 显示全部楼层    本楼为最佳答案   
Sub 求鱼()
Call 最小整数鱼(5, 1)
End Sub
Function countFish(ByVal PNumber As Long, ByVal SYCount As Long, ByVal fishNumber As Long)
Select Case SYCount
  Case PNumber '总人数。
     countFish = fishNumber * PNumber + 1
  Case Else '未达到总人数。继续递归。
     countFish = (countFish(PNumber, SYCount + 1, fishNumber) * PNumber) / (PNumber - 1) + 1
End Select
End Function
Function 最小整数鱼(ByVal PNumber As Long, ByVal SYCount As Long)
Do
m = m + 1
最小整数鱼 = countFish(PNumber, SYCount, m)
Loop Until 最小整数鱼 = Int(最小整数鱼)
Debug.Print PNumber & "人至少捕捞到" & 最小整数鱼 & "条鱼"
Debug.Print "第1人至少看到" & 最小整数鱼 & "条鱼"
For i = 2 To 5
s = Int(最小整数鱼 / PNumber) * (PNumber - 1)
Debug.Print "第" & i & "人至少看到" & s & "条鱼"
最小整数鱼 = s
Next i
End Function

评分

参与人数 1 +9 收起 理由
vbyou127 + 9 来学习

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2016-5-1 18:03 | 显示全部楼层
dsmch 发表于 2016-5-1 17:38

你的结果是错误的
回复

使用道具 举报

发表于 2016-5-1 23:09 | 显示全部楼层
vbyou127 发表于 2016-5-1 18:03
你的结果是错误的

没必要用递归计算吧。
  1. Sub test()
  2.     Do
  3.         m = m + 1
  4.         n = m
  5.         For i = 1 To 5
  6.             n = (n + 1) * 5
  7.             If n Mod 4 Then Exit For Else n = n / 4
  8.         Next
  9.         If i = 6 Then Exit Do
  10.     Loop
  11.     Debug.Print m; n + 1
  12. End Sub
复制代码
5个人每次分鱼都是去掉1条鱼,然后均分为5份然后拿走一份剩下4份,
所以倒推计算,就是*5/4得到单份,必须满足整数条件。

因此,迭代计算就是要求 n=(n+1)*5/4 仍是整数。如不是整数则无效跳过。

这样计算很快的。

评分

参与人数 2 +7 收起 理由
lichuanboy44 + 6 很给力
amzxfgh9632 + 1 很给力

查看全部评分

回复

使用道具 举报

发表于 2016-5-1 23:19 | 显示全部楼层
改为通用算法:
  1. Sub test()
  2.     k = 5 '分鱼人数 5人或6人或4人
  3.     y = 1 '每次扔掉的余数 1条或2条
  4.     Do
  5.         m = m + 1
  6.         n = m
  7.         For i = 1 To k
  8.             n = (n + y) * k
  9.             If n Mod (k - 1) Then Exit For Else n = n / (k - 1)
  10.         Next
  11.         If i = k + 1 Then Exit Do
  12.     Loop
  13.     Debug.Print k; y; n + y; m + y
  14.     '输出结果:人数、去除余数、最初时最多的鱼总数、最后一次时最少的鱼数
  15. End Sub
复制代码

评分

参与人数 3 +13 收起 理由
vbyou127 + 6 来学习
lichuanboy44 + 6 我和小伙伴都惊呆了
amzxfgh9632 + 1 很给力

查看全部评分

回复

使用道具 举报

发表于 2016-5-1 23:41 | 显示全部楼层
本帖最后由 香川群子 于 2016-5-1 23:46 编辑

即使写递归函数过程,也应该是:
  1. Sub test2()
  2.     k = 5 '分鱼总人数  如4人、5人、6人
  3.     y = 1 '每次扔掉的多余鱼数 如1 或2
  4.     Do
  5.         m = m + 1 '最大鱼数 (最初分鱼时)
  6.         n = dg(k, y, m, k) '调用递归计算求分到最后1次的数
  7.         If n = Int(n) Then Exit Do '如果n是整数则满足条件退出
  8.     Loop
  9.     Debug.Print k; y; n; m
  10. End Sub
  11. Function dg(k, y, m, t)
  12.     If t Then dg = (dg(k, y, m, t - 1) - y) / k * (k - 1) Else dg = m
  13.                       '下一次分鱼时数量 - 去除数 / 按人数k分以后 的剩余k-1份  一直递归到最初时的总数m
  14. End Function
复制代码
呵呵。
3楼的递归过程、其实是和我的迭代计算过程一样,是倒算的,虽然计算结果正确,
但并不是完全按照题目的原理顺序。我的递归过程才是完全符合题目原理的写法。


当然,按倒推计算的写法,计算效率会比较高……直接用Do循环迭代计算同时检查是否Mod (k-1)=0效率更高。

评分

参与人数 2 +10 收起 理由
vbyou127 + 9 来学习
amzxfgh9632 + 1 很给力

查看全部评分

回复

使用道具 举报

发表于 2016-5-2 07:41 | 显示全部楼层
与此相对应,倒推的递归过程应该这么写:
  1. Sub test2()       
  2.     k = 5 '分鱼总人数       
  3.     y = 1 '每次扔掉的多余鱼数       
  4.     Do       
  5.         m = m + 1 '最后一次的剩余鱼数       
  6.         n = dg2(k, y, m, 0) '递归倒推计算出最初的鱼总数n       
  7.         If n = Int(n) Then Exit Do        
  8.     Loop       
  9.     Debug.Print k; y; m + y; n + y       
  10. End Sub       
  11. Function dg2(k, y, m, t)       
  12.     If t < k Then dg2 = (dg2(k, y, m, t + 1) + y) * k / (k - 1) Else dg2 = m       
  13.     '每次倒推上一次鱼数为当前鱼数+多余数 * k份 / 剩余k-1份 一直递归到最后一次分剩下的鱼数          '       
  14. End Function
复制代码

评分

参与人数 1 +9 收起 理由
vbyou127 + 9 来学习

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-5-31 00:39 , Processed in 0.164149 second(s), 15 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表