2017年5月2日 星期二

Z2A,Z1A求組合數

4/28中午及5/1晚上加強,Z2A三位、Z1A三位,共6位到課
Vb2010 -Windows Form專案: 四個按鈕、二個文字方塊(輸入m,n),一個標籤(輸出)
M取N求組合數(二項係數) 0<=N<=M<=66,分四種解法
程式碼如下:


    Dim c(66, 66) As Long  '第4種解法使用
'解法一:呼叫函式 pk(k) 算出 k階乘 值,  0<=k<=66 ,但k=21 時溢位
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim m As Integer = TextBox1.Text
        Dim n As Integer = TextBox2.Text
        Label1.Text = pk(m) / pk(n) / pk(m - n)
    End Sub

    Function pk(ByVal k As Integer) As Long '函式 
        pk = 1
        For i = 2 To k
            pk *= i
        Next
    End Function
'解法二:先呼叫函式 pab(a,m):a*(a+1)*...*m  ,  a=max(n,m-n)+1
' 再除函式 pk(min(n,m-n)) ,但也在 m=30時溢位
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim m As Integer = TextBox1.Text
        Dim n As Integer = TextBox2.Text
        If n > m - n Then n = m - n
        ' 先算 a*...M  ,  a是?  呼叫 pab(a,m)
        Dim a As Integer = m - n + 1
        '再除 pk(n)
        Label1.Text = pab(a, m) / pk(n)
    End Sub
    Function pab(ByVal a As Integer, ByVal b As Integer) As Long
        'a*a+1*a+2*...b
        pab = 1
        For i = a To b
            pab *= i
        Next
    End Function
'解法三:純遞迴版呼叫 cmn(m,n) 
' cmn(m,n)={0 for m=0, 1 for n=0 , cmn(m-1,n)+cmn(m-1,n-1) for other }
    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Dim m As Integer = TextBox1.Text
        Dim n As Integer = TextBox2.Text
        Dim t1 As Date = Now
        Label1.Text = "純 C ( " & m & " , " & n & " ) = " & CMN(m, n)  '呼叫純遞迴版
        Label1.Text &= vbNewLine & DateDiff(DateInterval.Second, t1, Now)  'Cmn(29,14)約2秒,Cmn(30,15)約5秒
    End Sub
    Function CMN(ByVal m As Integer, ByVal n As Integer) As Long
       If m = 0 Then Return 0
        If n > m - n Then n = m - n   '選 n, m-n 中較小的為 n
         If n = 0 Then Return 1
        c(m, n) = CMN(m - 1, n) + CMN(m - 1, n - 1)
        Return c(m, n)
    End Function
'解法四:動態規劃,建陣列C(66,66)  遞迴版呼叫 cmn2(m,n)  
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' vb宣告長整數 c(66,66) 初值預設為 0 , 另先設定 n=0時的初值為 1
        For i = 0 To 66
            c(i, 0) = 1
        Next
    End Sub

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        Dim m As Integer = TextBox1.Text
        Dim n As Integer = TextBox2.Text
        Dim t1 As Date = Now
        Label1.Text = "陣列 C ( " & m & " , " & n & " ) = " & CMN2(m, n)  '呼叫陣列遞迴版
        Label1.Text &= vbNewLine & DateDiff(DateInterval.Second, t1, Now)  'Cmn2(66,33)<1秒
    End Sub
    Function CMN2(ByVal m As Integer, ByVal n As Integer) As Long
        If m = 0 Then Return 0    ' m=0傳回 0
       If n > m - n Then n = m - n
        If c(m, n) <> 0 Then Return c(m, n) '不為0 表示算過
         c(m, n) = CMN2(m - 1, n) + CMN2(m - 1, n - 1)
        Return c(m, n)

    End Function


0 意見:

張貼留言