关于递归算法学习
zipall吧
全部回复
仅看楼主
level 13
fengtf12 楼主
之前一直想学递归,却入不了门,今天无聊又去看了一下递归数组算一组数求和为某值,突然感觉悟了。在此立帖,一定要自己独立写出该递归算法。
2013年10月29日 03点10分 1
level 14
加油
2013年10月29日 04点10分 2
[太开心]谢谢~
2013年10月29日 04点10分
level 14
参透天机 渡劫成功[]
2013年10月29日 06点10分 3
[胜利]抽空又看了一遍siaojuen的复式回圈的遍历方法,感觉真牛,不过还是独爱递归
2013年10月29日 07点10分
level 13
fengtf12 楼主
Option Explicit
Dim arr, lastrow&, sum#
Dim re() As String
Sub 求和()
Dim i&, z&
Columns("c:c").ClearContents
ReDim re(1 To 1) As String
lastrow = Range("a" & Rows.Count).End(3).Row
arr = Range("a1:a" & lastrow).Value
sum = [b1].Value
Call 递归(1, 0, "")
[c1].Resize(UBound(re), 1).Value = Application.Transpose(re)
End Sub
Sub 递归(i&, nowval#, st$)
If arr(i, 1) + nowval = sum Then
re(UBound(re)) = st & arr(i, 1) & "=" & sum
ReDim Preserve re(1 To UBound(re) + 1) As String
GoTo x
End If
If i < lastrow And nowval < sum Then
If arr(i, 1) + nowval < sum Then Call 递归(i + 1, arr(i, 1) + nowval, st & arr(i, 1) & "+")
Call 递归(i + 1, nowval, st)
End If
x:
End Sub
上面的代码有问题,A1没有参加运算,在写最接近某值的时候发现了,改一下。I
2013年11月02日 04点11分 5
大侠 你当我刚才什么都没说啊 看到这层我已经吓尿
2013年11月13日 12点11分
回复 狂虐女友前男友 :哦?为什么啊?
2013年11月13日 12点11分
回复 fengtf12 :我是小白 对公式[不高兴]基本不懂 只有发晕的份儿
2013年11月13日 12点11分
回复 狂虐女友前男友 :可是这层跟牛没有关系,是其他程序代码。
2013年11月13日 13点11分
level 13
fengtf12 楼主
Option Explicit
Dim arr, lastrow&, sum
#, nowmin#
, minst$
Sub sum_if()
Dim i&, z&
Dim st$
sum = [b1].Value
nowmin = sum
lastrow = Range("a" & Rows.Count).End(3).Row
arr = Range("a1:a" & lastrow).Value
Call array_sum(1, 0, st)
[c1].Value = Mid(minst, 2) & "=" & Evaluate(minst)
End Sub
Sub array_sum(i&, nowval#, st$)
If arr(i, 1) + nowval = sum Then
[c1].Value = Mid(st, 2) & arr(i, 1) & "=" & sum
End
ElseIf Abs(nowval + arr(i, 1) - sum) < nowmin Then
minst = st & "+" & arr(i, 1)
nowmin = Abs(nowval + arr(i, 1) - sum)
End If
If i < lastrow And nowval < sum Then
Call array_sum(i + 1, nowval, st)
If arr(i, 1) + nowval < sum Then
Call array_sum(i + 1, nowval + arr(i, 1), st & "+" & arr(i, 1))
End If
End If
End Sub
一组数内N个数的和最接近某值的组合,刚刚犯了低级错误,我晕死~I
2013年11月02日 05点11分 7
[c1].Value = Mid(st, 2) & arr(i, 1) & "=" & sum 少了一个+号,[c1].Value = Mid(st, 2) & "+" & arr(i, 1) & "=" & sum
2013年11月02日 12点11分
If i < lastrow And nowval < sum Then 这句有点小问题,If i < lastrow And nowval < sum + nowmin Then 改成这样计算更准确。
2013年11月05日 04点11分
level 13
fengtf12 楼主
又写了几个递归过程,就不贴上来了,突然发现一件事
递归不能向普通代码一样,一步步调试着去研究,他需要的是确定一个终点,再如何起步即可,永远不要去想中间过程
不过对递归的出错调试方面,还是不太清楚
等将来更强大的我来补充吧。。。
2013年11月02日 12点11分 8
level 14
看不懂 支持一下是很有必要滴[献花]
2013年11月03日 02点11分 9
level 1
[泪]看不懂,楼主能不能做个模版出来。在某一列输入数组,在某个单元格输进定值,然后就能找出由那几个相加出来的~
2013年11月05日 04点11分 10
level 14
忽然想起一个算牛的帖子
用递归就要考虑每头牛的生老病死
而换个角度按岁数 则只考虑n岁的牛有多少只.
计算目标相同,但是效率完全不同.
https://tieba.baidu.com/p/926693324
2013年11月05日 07点11分 11
level 13
fengtf12 楼主
这题很多地方没写清楚:
1:牛刚出生是0岁还是1岁
2:牛在15岁的时候还会生么?
3:牛是20岁死还是21岁死
写了一个递归,时间原因来不及检查
Option Explicit
Dim arr() As Integer, i%
Sub niu()
ReDim arr(1) As Integer
i = Application.InputBox("年数")
Call n_niu(1)
End Sub
Sub n_niu(n%)
Dim z&, r&
If n >= i Then
For r = UBound(arr) To 1 Step -1
If arr(r) < 20 Then
z = z + 1
Else
Exit For
End If
Next
MsgBox z & "只"
Else
Dim arrsum&
arrsum = UBound(arr)
Do Until arrsum = 0 Or arr(arrsum) = 20
arr(arrsum) = arr(arrsum) + 1
If arr(arrsum) > 3 And arr(arrsum) < 15 Then z = z + 1
arrsum = arrsum - 1
Loop
ReDim Preserve arr(UBound(arr) + z) As Integer
Call n_niu(n + 1)
End If
End Sub
2013年11月05日 09点11分 12
level 13
fengtf12 楼主
回家又仔细一想,突然发现递归不需要这样算
重新写了一个,感觉不错
Function nian(n%) ‘n=多少年后
Dim i%, x%
If n < 20 Then nian = 1 '如果n>=20年,则这只牛已经死了,否则还活着,算1个
If n > 3 Then ’如果大于3年,第4年开始,这只牛可以生了
x = Application.Min(13, n - 1) ‘判断这只牛能生几只,最多是11只(15岁不能生的话)
For i = 3 To x '上面是n-1所以是从3 - x 最大 11只
nian = nian(n - i) + nian ’这只牛的后代总共是他生的牛的后代 + 他自己本身
Next
End If
End Function
验算了到了第8年,感觉是对的,后面太复杂,再验算下去头就大了,
还有一种递归思路,在n年的时候,1岁的牛的数量是 4-14岁牛的总数,这个思路怎么写还没想好,想到了再发。
2013年11月05日 11点11分 13
看了这帖子的回复,前辈写的递归思路跟这个很像[真棒]
2013年11月06日 02点11分
level 13
fengtf12 楼主
在楼上写了这么多,忘记贴题目了,补上
有一母牛,到 4 岁可生育,每年一头,所生均是一样的母牛,到15岁绝育,不再能生,20岁 死亡,问n年后有多少头牛
睡觉了,有空看一下前辈们是怎么解题的。
2013年11月05日 14点11分 15
想了许久,想从当年出生的牛有多少只递推到前20年出生的牛有多少只入手写递归,没想到最后下拉是错误的,无奈删除,有空再想把。
2013年11月05日 14点11分
level 13
fengtf12 楼主
Option Explicit
Function dangnian(n%)
If n = 1 Then dangnian = 1 '牛祖宗不是牛
妈妈生的
,是天生的。
If n > 3 Then
Dim dmaxs%, i%
dmaxs = Application.Min(n - 1, 13)
For i = 3 To dmaxs '当年出生的牛是前3年-前13年出生的牛的总数
dangnian = dangnian(n - i) + dangnian
Next
End If
End Function
Function zongshu(n%)
Dim i%, dmaxs%
dmaxs = Application.Max(1, n - 19)
For i = dmaxs To n '前19年-今年的牛都是活的,全部加起来就行了。
zongshu = dangnian(i) + zongshu
Next
End Function
自定义函数=zongshu(年份)
这个递归思路是把当年生的牛+前一年出生的牛+.....+前19年出生的牛,每一年加起来就是一共的牛,虽然这个递归思路效率低,不过也算一个思路,贴上来吧。
2013年11月06日 02点11分 16
level 13
fengtf12 楼主
Function text_niu(n%)
Dim arr(), i&, dmaxs&, r&
ReDim arr(n)
arr(1) = 1: If n < 20 Then text_niu = arr(1)
If n > 3 Then
For i = 4 To n
dmaxs = Application.Min(13, i - 1)
For r = 3 To dmaxs
arr(i) = arr(i - r) + arr(i)
Next
If n - 19 < i Then text_niu = text_niu + arr(i)
Next
End If
End Function
再把非递归的思路贴上
2013年11月06日 04点11分 17
level 12
看起来就深奥的要死 我还是去看喜羊羊吧[不高兴]
2013年11月06日 13点11分 18
level 13
fengtf12 楼主
在跟好友的讨论中,想出了新的思路,这个思路之前的帖子上好像没有[勉强]
Function newcow(n&)
If n < 0 Then
newcow = 0
ElseIf n < 4 Then
newcow = 1
Else
newcow = newcow(n - 1) + newcow(n - 4) - newcow(n - 15) - IIf(n = 20, 1, 0)
End If
End Function
这个过程已经经过修正(第一只牛在第1年里是1岁,其他牛出生是0岁,4岁生牛,15岁绝育,20岁不死,反正就跟原帖子一样了)
另外写了一个函数公式:
在第一行写:
=IF(ROW()<5,MAX(1,ROW()-2),SUM(SUMIF(OFFSET(INDIRECT("rc",),-IF({1,1,0},{1,4,0},IF(ROW()>14,14+(ROW()>15),-9999)),,),">0")*{1,1,-1}))-(ROW()=20)
数组公式,三键结束,下拉,
嗯,到这里我觉得我可以@zipall 了,怎么样?这个递归思路还算新颖吧?
2013年11月13日 12点11分 19
这里说明一下为什么是IF(ROW()>14,14+(ROW()>15),-9999),因为第一只牛第一年就是1岁,其他牛第一年只有0岁,所以只有第一只牛绝育的时候是14年后,其他牛是15年后。
2013年11月13日 12点11分
再说明一下自定义函数的几个地方的问题,因为第一只牛出生就是1岁,所以我们只能假定第一只牛在第0年的时候是0岁,就存在,这样就可以统一了,否则还要加一个elseif n = 4 then,也是为什么iif(n=20,1,0)(因为第一只牛出生就是1岁,比其他牛少1年寿命)
2013年11月13日 12点11分
回复 fengtf12 :先顶一下 热烈庆祝大侠灵光闪现 豁然开朗
2013年11月13日 12点11分
手机看帖,先恭喜一下!回头仔细研究
2013年11月13日 13点11分
level 11
都是大神级别的人物啊,先膜拜一下,一下子变小白,咋跟看天书似的...[泪][泪]
2013年11月13日 16点11分 20
慢慢来[哈哈]
2013年11月13日 22点11分
level 13
fengtf12 楼主
另外说明一下为什么数牛这题为什么递归跟普通function运算速度相差这么大,主要原因是这个递归过程重复计算的次数实在太多导致的,其实递归虽然要略微慢一点,但是没有这么离谱,比如定义一个公共数组,让重复计算的次数减少:
Dim cow(-15 To 5000)
Function newcow(n&)
If cow(n) > 0 Then newcow = cow(n): Exit Function
If n < 0 Then
newcow = 0
ElseIf n < 4 Then
newcow = 1
Else
newcow = newcow(n - 1) + newcow(n - 4) - newcow(n - 15) - IIf(n = 20, 1, 0)
End If
cow(n) = newcow
End Function
2013年11月14日 03点11分 21
1