| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 711 人关注过本帖
标题:给初学者----递归及应用
只看楼主 加入收藏
xinfresh
Rank: 4
等 级:贵宾
威 望:13
帖 子:594
专家分:0
注 册:2006-1-13
收藏
 问题点数:0 回复次数:1 
给初学者----递归及应用

前一段时间在论坛上逛,看到几个问题:
一是说,用0~9这10个数字组成一个1位数+2个数+3位数=4位数的算式(各位数字不重复)
二是说,用1~9这9个数字组成一个9位数(各位上数字不重复),使满足前三位能被3整除,前四位能被4整除,……以此类推
三是说,说什么来着,忘了,呵……不好意思

这种题目一口就能说出解题方法:
把所有可能的排列都列出来,然后一个个按条件检验
问题是光知道解法有什么用?我问你:我80岁的时候长什么样?你说:等吧,到了那天就知道了。实话,大实话,这孩子没啥毛病就是太诚实……想抽你……太实话了就是废话了!

排列麻烦在哪?如果不是排列,也就是说允许数字重复出现就很容易做,拿第一个题目来说,如果可以重复,不就是从0~9999999999的循环吗?
For m=0 to 9999999999
....按条件来试
Next
把每个数拆开看,看成方程中的项就完了呗。一个循环就够了。

这种循环可不可以做排列呢?也是可以的,只是同时要加上一个小条件:a(0)<>a(1) and a(0)<>a(2) and a(0)<>a(3) and a(0)<>a(4) and a(0)<>a(5) and a(0)<>a(6) and a(0)<>a(7) and a(0)<>a(8) and a(0)<>a(9) and a(1)<>a(2) and a(1)<>a(3) and a(1)<>a(4) and a(1)<>a(5) and a(1)<>a(6) and a(1)<>a(7) and a(1)<>a(8) and a(1)<>a(9) and a(2)<>a(3) and a(2)<>a(4) and a(2)<>a(5) and a(2)<>a(6) and a(2)<>a(7) and a(2)<>a(8) and a(2)<>a(9) and a(3)<>a(4) and a(3)<>a(5) and a(3)<>a(6) and a(3)<>a(7) and a(3)<>a(8) and a(3)<>a(9) and a(4)<>a(5) and a(4)<>a(6) and a(4)<>a(7) and a(4)<>a(8) and a(4)<>a(9) and a(5)<>a(6) and a(5)<>a(7) and a(5)<>a(8) and a(5)<>a(9) and a(6)<>a(7) and a(6)<>a(8) and a(6)<>a(9) and a(7)<>a(8) and a(7)<>a(9) and a(8)<>a(9),两两不相等,这不就是全排列了吗?(我才没这么闲打这么多字呢,程序输出的啦)
如果你喜欢代码量大一点,这样成就感多一点,我没话。

关键就是用什么方法能快速的实现全排列。
递归。

什么是递归?随便说说,递归,那不就一个传“递”,一个回“归”,把当前的状态的参数传递到下一级节点,直到某一节点不能向下传递为止,那时将返回上一级节点,从上一级节点处寻找其它可执行的节点,没有找到就返回再上一级的节点。

最常见的例子就是n!(教材都是互相抄的!)
VB代码可以写成:
Private Sub Command1_Click()
Dim x As Integer
Dim y As Integer
x = Val(Text1.Text)
y = Recur(x)
Print y
End Sub
Private Function Recur(ByVal t As Integer) As Integer
If t = 1 Then
Recur = 1
Else
Recur = t * Recur(t - 1)
End If
End Function
关键就是这个Recur(),有规律的调用本身的运算应该都可以用递归来做。
取n的时候,Recur(n)等于n*Recur(n-1),于是调用Recur(n-1)计算,就是“递”,Recur(n-1)又等于(n-1)*Recur(n-2),于是继续向下调用……直到Recur(2)=2*Recur(1),Recur(1)就等于1,于是“递”停止,可以开始归了,一级一级向上返回值,Recur(2)=2*Recur(1)=2*1,如此向上,直到Recur(n)得到结果,于是“归”停止。

学过一点编程的,这个例子应该都能看懂。
不过,看了这个例子,可能还是想不到上面的题怎么解,先看代码吧:
Option Explicit
Const Fv = 10 '一个不可能出现的数,用于判断该位是否空闲
Dim SData(9) As Integer
Private Sub Command1_Click()
Dim Z(9) As Integer
Dim m As Integer
'Z为判断数组,SData为待排列数组
For m = 0 To 9
SData(m) = m
Z(m) = Fv
Next
红色区,赋初值和标记值
Call Recursion(Z, 0)
MsgBox "Done" & vbCrLf & "共有:" & List1.ListCount & "组"
End Sub
Private Sub Recursion(ByRef Jud() As Integer, ByVal Pos As Integer) '核心递归过程
Dim m As Integer, k As Integer
Dim temp As Integer
Dim s As String
'复制临时数组Td
Dim Td(9) As Integer

If Pos > 9 Then
If Jud(1) <> 0 And Jud(3) <> 0 And Jud(6) <> 0 Then '要求的判断条件
If Jud(0) + (10 * Jud(1) + Jud(2)) + (100 * Jud(3) + 10 * Jud(4) + Jud(5)) = 1000 * Jud(6) + 100 * Jud(7) + 10 * Jud(8) + Jud(9) Then
s = CStr(Jud(0)) & "+" & CStr(Jud(1)) & CStr(Jud(2)) & "+" & CStr(Jud(3)) & CStr(Jud(4)) & CStr(Jud(5)) & "=" & CStr(Jud(6)) & CStr(Jud(7)) & CStr(Jud(8)) & CStr(Jud(9))
List1.AddItem s
Me.Refresh
End If
End If
仅仅是判断条件,可以不看
Exit Sub
End If

temp = SData(Pos)
For m = 0 To 9
If Jud(m) = Fv Then
For k = 0 To 9
Td(k) = Jud(k)
Next
Td(m) = temp
这一步修改了标记值!!!!
Call Recursion(Td, Pos + 1)
传到下一级,"递"
End If
Next

End Sub
思想是:
1,设一个长度为10的数组Z(),做为标记数组(标记什么后面说),这个数组的每个元素就代表要做的十位数全排列的每一位,给这个数组赋一个除0~9以外的值做为初值Fv。
2,从0~9之中,按一定顺序(比如就按从0到9的顺序)一个一个选出数字,循环查看Z()中的哪些位是可用的(还是Fv),如果还是初值没变说明可用,如果已经是0~9中的数值了,说明该位已经被该数值填过了,就不可用,所以标记也就是标记该位是否可以填入其它数字。之后,取第一个可用的位填上,也就是赋值,再取下一个数,再查看还剩哪些位可用,也取第一个填上……
3,关键在这!由于填充是循环的,对每个数字来说,程序最终都会把所有可用的位填一遍,这样就回到了数学上排列的最初含意。A(5,2)=20的本意不就是说,有5个空位,2个物体要往里面填,第一个放的时候有5个位可选,第一个放好后,第二个还有4个位可选吗,所以才是5*4=20,递归也是这样的:
第一个数字0,有10个空位可选,先填第一个可用位,等到把0*********全排完了,0选位所用的循环还在继续,再选第二个可用位,等*0********选完了,0选位所用循环还在,那再选第三个可用位……
在0*********的条件下,下一个数字是1,1有9个空位可选,先选第一个可用位,等到01********全排完了,1的选位循环会再选第二个可用位,0*1*******
以此类排
这样就能把所有的情况排出来,共有10*9*8*7*6*5*4*3*2*1=3628800种情况。

只要会用递归把全排列做出来这类题目不都不用教了吗?

搜索更多相关主题的帖子: 递归 应用 
2006-01-19 12:09
xinfresh
Rank: 4
等 级:贵宾
威 望:13
帖 子:594
专家分:0
注 册:2006-1-13
收藏
得分:0 
后悔了,应该发个系列就好了,一次发太多字,没几个人有耐心看完

E-mail:xinfresh@QQ:383094053校内:http:///getuser.do?id=234719042
2006-02-02 18:32
快速回复:给初学者----递归及应用
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.027462 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved