用两种方法求解九宫算问题

问题:

在一个3*3的方格内填入9个数字,数字的范围从1~9,每个数字仅出现一次,使得每行、每列以及两个对角线的数字之和为15。

 一、VBA程序

算法思路:

1、将9个数字分成3组,每组3个数字,使得每组数字之和为15。

2、将第二个数字为5个分组单独选出,作为方格的第二行数组。

3、循环抽取其它的分组,与第二分组进行重复性判断。

4、如果没有重复,记录这3种分组。

5、将这3种分组传人判断函数,核实是否满足条件。

6、如果满足条件,将结果输出。

 VBA源程序如下:



运行结果

6  7  2

Sub jiugongsuan_All()

Dim cs(1 To 9) As Integer
Dim jgs1(1 To 3) As Integer
Dim Ot() As Integer
'第一、三行数组
Dim Sec() As Integer
'第二行数组
Dim temp1(1 To 100, 1 To 3) As Integer
Dim temp2(1 To 100, 1 To 3) As Integer
'temp1、temp2分别为临时数组
Dim Totali As Integer
'第二个数为5,三个数之和为15的数组个数
Dim Totaln As Integer
'不包括第二个数为5,三个数之和为15的数组个数
Dim at(1 To 3) As Integer
Dim bt(1 To 3) As Integer
Dim ct(1 To 3) As Integer
'at、bt、ct分别为中间变量数组

Dim scjg(1 To 3, 1 To 3) As Integer
'scjg为结果数组


Dim i As Integer

Totali = 0
Totaln = 0

For i = 1 To 9
'初始数组赋值
cs(i) = i

Next

For m = 1 To 9
 If cs(m) <> 0 Then
'   判断该数字是否已被占用
   jgs1(1) = cs(m)
   cs(m) = 0
'   占用该数字
    
   For n = 1 To 9
    If cs(n) <> 0 Then
       jgs1(2) = cs(n)
        cs(n) = 0
        
      For q = 1 To 9
        If cs(q) <> 0 Then
         jgs1(3) = cs(q)
          cs(q) = 0
     
       
            If jgs1(1) + jgs1(2) + jgs1(3) = 15 Then
      
             ' Debug.Print jgs1(1); jgs1(2); jgs1(3)
                 
               If jgs1(2) = 5 Then
               '第二行数据
                 Totali = Totali + 1
                temp1(Totali, 1) = jgs1(1)
                temp1(Totali, 2) = jgs1(2)
                temp1(Totali, 3) = jgs1(3)
               Else
'                第一行,第三行数据
                 Totaln = Totaln + 1
                temp2(Totaln, 1) = jgs1(1)
                temp2(Totaln, 2) = jgs1(2)
                temp2(Totaln, 3) = jgs1(3)
              
                     
              
              End If
              
              
                 
             End If
      
            cs(q) = q
            End If
       
       Next
       
         cs(n) = n
       End If
       
       
       Next
     
     cs(m) = m
 End If
 

 
Next

ReDim Sec(1 To Totali, 1 To 3)
ReDim Ot(1 To Totaln, 1 To 3)


For m1 = 1 To Totali
Sec(m1, 1) = temp1(m1, 1)
Sec(m1, 2) = temp1(m1, 2)
Sec(m1, 3) = temp1(m1, 3)

'第二行数组赋值

Next

For n1 = 1 To Totaln
Ot(n1, 1) = temp2(n1, 1)
Ot(n1, 2) = temp2(n1, 2)
Ot(n1, 3) = temp2(n1, 3)

Next

'第一、三行数组赋值

For m1 = 1 To Totali

    bt(1) = Sec(m1, 1)
    bt(2) = Sec(m1, 2)
    bt(3) = Sec(m1, 3)
   
     For n1 = 1 To Totaln
       at(1) = Ot(n1, 1)
       at(2) = Ot(n1, 2)
       at(3) = Ot(n1, 3)
       
     If cfpd(at, bt) Then
 
           
      Else
    
      For k1 = 1 To Totaln
       ct(1) = Ot(k1, 1)
       ct(2) = Ot(k1, 2)
       ct(3) = Ot(k1, 3)
       
      
      If Not cfpd(at, ct) And Not cfpd(bt, ct) Then
'          第一、三行,第二、三行重复情况判断
     
      scjg(1, 1) = at(1)
      scjg(1, 2) = at(2)
      scjg(1, 3) = at(3)
      scjg(2, 1) = bt(1)
      scjg(2, 2) = bt(2)
      scjg(2, 3) = bt(3)
      scjg(3, 1) = ct(1)
      scjg(3, 2) = ct(2)
      scjg(3, 3) = ct(3)

'       调用函数
       finalpd (scjg)
    
    Else
     
   
    End If
 
        
     
     Next
     
     End If
       
    Next

Next


End Sub

Function cfpd(a() As Integer, b() As Integer) As Boolean
'2个数组重复情况判断


 If b(1) <> a(1) And b(1) <> a(2) And b(1) <> a(3) Then
  cfpd = False
 Else
  cfpd = True
  Exit Function
  
 End If
 
 If b(2) <> a(1) And b(2) <> a(2) And b(2) <> a(3) Then
 cfpd = False
 Else
 cfpd = True
 Exit Function
 
 End If
 
 If b(3) <> a(1) And b(3) <> a(2) And b(3) <> a(3) Then
 cfpd = False
Else
 cfpd = True
 Exit Function
 
 
End If

End Function


Sub finalpd(sz As Variant)
'列求和、对角线求和判断

Dim i%, j%
Dim myjgs(1 To 3, 1 To 3)
Dim Hpd As Boolean
Dim Lpd As Boolean
Dim DJXpd As Boolean


For i = 1 To 3
 For j = 1 To 3
 myjgs(i, j) = sz(i, j)

 Next
Next


'列判断
For i = 1 To 3

If myjgs(1, i) + myjgs(2, i) + myjgs(3, i) = 15 Then
Lpd = True
Else
Lpd = False
Exit For
End If

Next

'对角线判断

If myjgs(1, 1) + myjgs(2, 2) + myjgs(3, 3) = 15 And myjgs(1, 3) + myjgs(2, 2) + myjgs(3, 1) = 15 Then
 DJXpd = True

Else
 DJXpd = False
End If


If Lpd And DJXpd Then

'结果输出

Debug.Print myjgs(1, 1); myjgs(1, 2); myjgs(1, 3)

Debug.Print myjgs(2, 1); myjgs(2, 2); myjgs(2, 3)

Debug.Print myjgs(3, 1); myjgs(3, 2); myjgs(3, 3)

Debug.Print "-------------------------"

End If


End Sub

运行结果:

6  7  2

1  5  9

8  3  4

-------------------------

 8 3  4

 1 5  9

 6 7  2

-------------------------

 4 9  2

 3 5  7

 8 1  6

-------------------------

 8 1  6

 3 5  7

 4 9  2

-------------------------

 2 9  4

 7 5  3

 6 1  8

-------------------------

 6  1  8

 7 5  3

 2 9  4

-------------------------

 2 7  6

 9 5  1

 4 3  8

-------------------------

 4 3  8

 9 5  1

 2 7  6 

  

二、EXCEL规划求解

1、选择数据菜单-à“规划求解”

2、设置可变单元格及约束条件

约束条件

Ø  行之和为15

Ø  列之和为15

Ø  所有数字均为整数

Ø  所有数字>=1

Ø  所有数字<=9

Ø  所有数字连乘的积为9的阶乘,这种方式可以限制每个数字出现1次,且仅出现1次。

用两种方法求解九宫算问题_第1张图片 

图一

用两种方法求解九宫算问题_第2张图片

图二

这种方法只能求出一个解。

你可能感兴趣的:(VBA,EXCEL)