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

8 篇文章 0 订阅

问题:

在一个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次。

 

图一

图二

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用 C 语言实现求解九宫图的程序: ```c #include <stdio.h> #include <stdbool.h> #define SIZE 9 // 定义九宫图大小 int puzzle[SIZE][SIZE]; // 存储九宫图的二维数组 // 检查当前数字是否可放置在该位置 bool is_valid(int row, int col, int num) { // 检查当前行和列是否有重复数字 for (int i = 0; i < SIZE; i++) { if (puzzle[row][i] == num || puzzle[i][col] == num) { return false; } } // 检查当前宫格是否有重复数字 int start_row = row / 3 * 3; int start_col = col / 3 * 3; for (int i = start_row; i < start_row + 3; i++) { for (int j = start_col; j < start_col + 3; j++) { if (puzzle[i][j] == num) { return false; } } } return true; } // 递归求解九宫图 bool solve(int row, int col) { // 如果已经到达最后一个格子,返回 true 表示已经求解成功 if (row == SIZE) { return true; } // 如果当前格子已经有数字,则跳过继续求解下一个格子 if (puzzle[row][col] != 0) { if (col == SIZE - 1) { return solve(row + 1, 0); } else { return solve(row, col + 1); } } // 尝试在当前格子放置数字 1~9 中的一个 for (int i = 1; i <= 9; i++) { if (is_valid(row, col, i)) { puzzle[row][col] = i; if (col == SIZE - 1) { if (solve(row + 1, 0)) { return true; } } else { if (solve(row, col + 1)) { return true; } } puzzle[row][col] = 0; } } return false; } int main() { // 初始化九宫图 printf("请输入九宫图,空格用 0 表示:\n"); for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { scanf("%d", &puzzle[i][j]); } } // 求解九宫图 if (solve(0, 0)) { printf("求解成功,结果为:\n"); for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { printf("%d ", puzzle[i][j]); } printf("\n"); } } else { printf("无解!\n"); } return 0; } ``` 在程序中,`puzzle` 数组用来存储九宫图,其中空白格用 `0` 表示。`is_valid` 函数用来检查当前数字是否可放置在该位置,`solve` 函数是递归求解九宫图的主要函数。程序先读入九宫图,然后调用 `solve` 函数求解,最后输出结果。如果求解成功,会输出求解后的九宫图;如果无解,会输出 "无解!"。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值