| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 773 人关注过本帖, 1 人收藏
标题:九宫格 也就是魔方阵 ,用递归写了一个,我无法继续优化
只看楼主 加入收藏
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
结帖率:100%
收藏(1)
已结贴  问题点数:20 回复次数:3 
九宫格 也就是魔方阵 ,用递归写了一个,我无法继续优化
九宫格 也就是魔方阵 ,用递归写了一个,我无法继续优化


程序代码:
Option Explicit

Private Type 数据类型
    Value As Long           '当前值
    Hw() As Long         '范围
    Index As Long           '当前范围指针
    Count As Long           '范围总数
End Type

Dim AA() As 数据类型
Dim MFJ As Long
Dim MFG As Long

Private Sub Command1_Click()

Text1.Text = ""

MFJ = val(Text2.Text)
If MFJ < 3 Then MFJ = 3

MFG = MFJ * MFJ

ReDim AA(MFG)
Dim i As Long
Dim j As Long

Dim js As Long
Dim js2 As Long

For i = 1 To MFG
    ReDim AA(i).Hw(MFG)
    AA(1).Hw(i) = i                         '第一个元素的范围是全满
    AA(i).Index = 1                         '指针均先指向1
Next i
    AA(1).Count = MFG                       '第一个元素永远是满范围

    
    '第一个元素
    AA(1).Index = 1
    AA(1).Value = AA(1).Hw(AA(1).Index)
    
    For j = 2 To MFG                    '求后面的元素的范围
        Call 计算范围(j)
    Next j
   
   
    js = 0      '结果个数计数
    i = 0       '显示进度用
    'js2 = 0

'此循环次数是: MFG阶乘 次,已是最优化结果了
Do
    'js2 = js2 + 1
    If 是否相等 Then
        js = js + 1
        Call 输出结果
    End If
    
    If i <> AA(1).Index Then
        Label1 = "进度:" & AA(1).Index
        DoEvents
    End If
    'Label3.Caption = js2
    'DoEvents
    
Loop While 索引加(MFG)
Label2.Caption = "结果总数:" & js

End Sub

Private Function 索引加(cs As Long) As Boolean
AA(cs).Index = AA(cs).Index + 1
If AA(cs).Index > AA(cs).Count Then
    If cs > 1 Then
        索引加 = 索引加(cs - 1)
        Call 计算范围(cs)
    Else
        索引加 = False
    End If
Else
    AA(cs).Value = AA(cs).Hw(AA(cs).Index)
    索引加 = True
End If

End Function

Private Sub 计算范围(cs As Long)
Dim i As Long, j As Long
Dim b() As Long
ReDim b(MFG)

'生成所有可能
For i = 1 To MFG
    b(i) = i
Next i

'去掉已出现了的数据
For i = 1 To cs - 1
    For j = 1 To MFG
        If b(j) = AA(i).Value Then
            b(j) = 0
            Exit For
        End If
    Next j
Next i

'计数,剩下多少数据
j = 0
For i = 1 To MFG
    If b(i) > 0 Then
        j = j + 1
    End If
Next i

'初始化范围大小,设置总数,索引
ReDim AA(cs).Hw(j)
AA(cs).Count = j
AA(cs).Index = 1

'填写范围
j = 0
For i = 1 To MFG
    If b(i) > 0 Then
        j = j + 1
        AA(cs).Hw(j) = b(i)
    End If
Next i
AA(cs).Value = AA(cs).Hw(1)


End Sub




Private Sub Form_Load()

MFJ = 3

End Sub

Private Function 是否相等() As Boolean
'是否符合魔方阵的情况,横竖相等,对角线也等
Dim i As Long, j As Long
Dim k As Long, o As Long
Dim js As Long

    是否相等 = True

For i = 1 To MFJ                '第一个值
    k = k + AA(i).Value
Next i

For i = 2 To MFJ                            '
    o = 0
    For j = 1 To MFJ
      o = AA((i - 1) * MFJ + j).Value + o
    Next j
    If o = k Then
        js = js + 1
    Else
        是否相等 = False
        Exit Function
    End If
Next i

For i = 1 To MFJ                             '
    o = 0
    For j = 1 To MFJ
        o = AA(i + (j - 1) * MFJ).Value + o
    Next j
    If o = k Then
        js = js + 1
    Else
        是否相等 = False
        Exit Function
    End If
Next i

o = 0
For i = 1 To MFJ                            '对角线1
    o = o + AA(i * MFJ - i + 1).Value
Next i
If o = k Then
    js = js + 1
Else
    是否相等 = False
    Exit Function
End If

o = 0
For i = 1 To MFJ                            '对角线2
    o = o + AA((i - 1) * MFJ + i).Value
Next i
If o = k Then
    js = js + 1
Else
    是否相等 = False
    Exit Function
End If

End Function

Private Sub 输出结果()
Dim i As Long
Dim s As String
Dim s2 As String

For i = 1 To MFG
    s = s & AA(i).Value & "  "
    If i Mod MFJ = 0 Then
        s = s & vbCrLf
    End If
Next i
s = s & String(3 * MFJ, "-")

s2 = Text1.Text
If Len(s2) > 0 Then
    s2 = s2 & vbCrLf & s
Else
    s2 = s
End If

Text1.Text = s2

End Sub


请论坛牛的人,帮忙优化,减少循环次数。
搜索更多相关主题的帖子: 优化 数据 九宫格 
2011-09-07 18:00
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:0 
优化了二个函数。减少了运算量,感觉速度有明显上升。当然,穷举 》4 阶以 魔方阵还是很慢的。

程序代码:

Private Sub Command1_Click()
Text1.Text = ""

MFJ = Val(Text2.Text)
If MFJ < 3 Then MFJ = 3

MFG = MFJ * MFJ

ReDim AA(MFG)
Dim i As Long
Dim j As Long

Dim js As Long

For i = 1 To MFG
    ReDim AA(i).Hw(MFG - i + 1)
    AA(i).Count = MFG - i + 1
    
    AA(1).Hw(i) = i                         '第一个元素的范围是全满
    AA(i).Index = 1                         '指针均先指向1
Next i
    AA(1).Count = MFG                       '第一个元素永远是满范围

    
    '第一个元素
    AA(1).Index = 1
    AA(1).Value = AA(1).Hw(AA(1).Index)
    
    For j = 2 To MFG                    '求后面的元素的范围
        Call 计算范围(j)
    Next j
   
   
    js = 0      '结果个数计数
    i = 0       '显示进度用
 '此循环次数是: MFG阶乘 次,已是最优化结果了
Do
    If 是否相等 Then
        js = js + 1
        Call 输出结果
    End If
    
    If i <> AA(1).Index Then
        i = AA(1).Index
        Label1 = "进度:" & i
        DoEvents
    End If
    
Loop While 索引加(MFG)
Label2.Caption = "结果总数:" & js

End Sub

Private Function 索引加(cs As Long) As Boolean
'此函数为递归调用

Dim i As Long, j As Long
Dim yb As Boolean

If cs = MFG Then                        '最后一个参数
    If 索引加(cs - 1) Then                  '确定前一个值,真
        For i = 1 To MFG                    '然后再来查找未使用的值
            yb = True                       '
            For j = 1 To MFG - 1            '除下最后一个元素
                If i = AA(j).Value Then     '判断值
                    yb = False              '找到,假
                    Exit For
                End If
            Next j
            If yb Then                      '找到未使用的元素
                AA(MFG).Value = i
                Exit For
            End If
        Next i
        索引加 = True
    Else
        索引加 = False
    End If
    
Else
    AA(cs).Index = AA(cs).Index + 1
    If AA(cs).Index > AA(cs).Count Then
        If cs > 1 Then
            索引加 = 索引加(cs - 1)
            Call 计算范围(cs)
        Else
            索引加 = False
        End If
    Else
        AA(cs).Value = AA(cs).Hw(AA(cs).Index)
        索引加 = True
    End If
End If

End Function


Private Sub 计算范围(cs As Long)
Dim i As Long, j As Long
Dim k As Long

'Dim b() As Long
'ReDim b(MFG)

Dim CB As Boolean

k = 0                                    '计数
For i = 1 To MFG                         '所有的可能
    CB = True                            '设置为 真,
    For j = 1 To cs - 1                     '搜索前面的值
        If AA(j).Value = i Then         '发现重复
            CB = False                  '设为假
            Exit For                    '退出循环
        End If
    Next j
    If CB Then                          '如果未发现重复
        k = k + 1                       '计数
        AA(cs).Hw(k) = i                '设置到范围内云
    End If
Next i
AA(cs).Index = 1                        '索引为1
AA(cs).Value = AA(cs).Hw(1)             '取值



''生成所有可能
'For i = 1 To MFG
'    b(i) = i
'Next i
'
''去掉已出现了的数据
'For i = 1 To cs - 1
'    For j = 1 To MFG
'        If b(j) = AA(i).Value Then
'            b(j) = 0
'            Exit For
'        End If
'    Next j
'Next i
'
''计数,剩下多少数据
'j = 0
'For i = 1 To MFG
'    If b(i) > 0 Then
'        j = j + 1
'    End If
'Next i
'
''初始化范围大小,设置总数,索引
'ReDim AA(cs).Hw(j)
'AA(cs).Count = j
'AA(cs).Index = 1
'
''填写范围
'j = 0
'For i = 1 To MFG
'    If b(i) > 0 Then
'        j = j + 1
'        AA(cs).Hw(j) = b(i)
'    End If
'Next i
'AA(cs).Value = AA(cs).Hw(1)

End Sub


[ 本帖最后由 风吹过b 于 2011-9-8 17:34 编辑 ]

授人于鱼,不如授人于渔
早已停用QQ了
2011-09-08 17:31
编程的乐趣
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:1
帖 子:229
专家分:1027
注 册:2011-4-4
收藏
得分:20 
呵呵
2011-09-08 18:46
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:0 
用公式算法填 魔方阵,仅完成奇数部分,偶数部分,4X 部分,不去弄了。直接百度一下,然后按算法写就是了。

程序代码:
Option Explicit

Dim AA() As Long
Dim MFJ As Long             '阶数
Dim MFG As Long             '总个数

Private Sub Command1_Click()

Text1.Text = ""

MFJ = Val(Text2.Text)
If MFJ < 3 Then MFJ = 3

Dim i As Long, j As Long
Dim X As Long, y As Long
Dim x1 As Long, y1 As Long
    MFG = MFJ * MFJ                 '总元素个数
    ReDim AA(MFJ, MFJ)                   '重定义数组

If MFJ Mod 2 = 1 Then                   '奇数魔方阵

    '魔方阵的排列规律(奇数阵):
    '⑴将1放在第一行中间一列?
    '⑵从2开始直到n×n止各数依次按下列规则存放:每一个数存放的行比前一个数的行数减1,列数加1。
    '⑶如果上一个数的行数为1,则下一个数的行数为n,列数加1。如果上一个数的列数的n时,下一个数的列数为1,行数减1。
    '⑷如果按上面的规则确定的位置上已有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面。
    
    
    '填 1 部分
    X = 1                       '1行
    y = Int(MFJ / 2) + 1        '中间列
    AA(X, y) = 1                '给值
    For i = 2 To MFG            '从2开始
        x1 = X - 1              '第2条、3条规则始
        If x1 < 1 Then
            x1 = MFJ
        End If
        y1 = y + 1
        If y1 > MFJ Then
            y1 = 1
        End If                  '第2条、3条规则结束
        If AA(x1, y1) > 0 Then  '判断是否符合第4条规则
            x1 = X + 1          '计算第4条规则
            If x1 > MFJ Then
                x1 = 1
            End If
            y1 = y
       
        End If
            AA(x1, y1) = i      '给值
            X = x1              '当前位置
            y = y1
    Next i
    
End If
    
    Call 输出结果



'Label2.Caption = "结果总数:" & js

End Sub


Private Sub 输出结果()
Dim i As Long, j As Long
Dim s As String
Dim s2 As String
s = ""
For i = 1 To MFJ
    For j = 1 To MFJ
    Select Case Int(Log10(AA(i, j) + 1))
        Case 0
            s = s & "     " & AA(i, j)
        Case 1
            s = s & "    " & AA(i, j)
        Case 2
            s = s & "   " & AA(i, j)
        Case 3
            s = s & "  " & AA(i, j)
        Case Else
            s = s & " " & AA(i, j)
    End Select
   Next j
    s = s & vbCrLf
Next i

s = s & String(3 * MFJ, "-")

s2 = Text1.Text
If Len(s2) > 0 Then
    s2 = s2 & vbCrLf & s
Else
    s2 = s
End If

Text1.Text = s2

End Sub


Static Function Log10(X)
   Log10 = Log(X) / Log(10#)
End Function




[ 本帖最后由 风吹过b 于 2011-9-9 17:22 编辑 ]

授人于鱼,不如授人于渔
早已停用QQ了
2011-09-09 17:19
快速回复:九宫格 也就是魔方阵 ,用递归写了一个,我无法继续优化
数据加载中...
 
   



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

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