📅  最后修改于: 2023-12-03 15:28:42.546000             🧑  作者: Mango
这是一道 GATE 计算机科学考试的题目,需要对程序员进行一定的挑战才能完成。
在一个 n x n 的方形表格中填入 1~n 的数,要求填成一个 n 阶幻方,即每行、每列和对角线上的数字加起来都相等。
给定整数 n (3≤n≤100)。请编写一个程序,以填出所有合法的 n 阶幻方。
一个整数 n。
所有合法的 n 阶幻方,每个幻方需用每行数字以空格隔开,行末无空格。
下面是一个可能的输出示例:
1 15 14 4
12 6 7 9
8 10 11 5
13 3 2 16
1 12 15 8 57 56 29 36
14 7 6 9 54 59 34 27
19 23 24 20 43 40 47 51
32 30 25 18 41 46 53 55
37 42 39 44 26 17 22 31
52 50 45 38 21 28 33 35
49 41 38 43 22 11 14 31
40 34 29 20 60 51 54 47
本题需要使用回溯法进行求解,具体思路如下:
将幻方的第一行进行初始化,以保证每行的和相等。
对于幻方中每一个位置,从 1 开始尝试填入数字,每填入一个数字,在判断该行或该列与斜线的和是否相等。
如果全部位置都已填写,则输出该幻方。
如果当前填写的数字已经大于 n,则回退到上一个位置尝试其他数字。
如果所有数字都尝试了,都不能满足要求,则回退到上一个位置尝试其他数字。如果回退时回到了第一列,则说明幻方填写失败。
下面是 Python 代码片段:
# 初始化幻方的第一行,sum_list 是每行每列和的列表
def init_square(square_size):
square = [[0] * square_size for i in range(square_size)]
square[0][square_size//2] = 1
i, j = 0, square_size//2
for n in range(2, square_size**2+1):
i -= 1
j += 1
if i < 0 and j < square_size:
i = square_size - 1
elif j == square_size and i >= 0:
j = 0
elif i < 0 and j == square_size:
i, j = 0, square_size - 2
if square[i][j] != 0:
i += 1
j -= 2
square[i][j] = n
return square
# 回溯求解幻方
def magic_square(square_size):
square = [[0] * square_size for i in range(square_size)]
sum_list = [0] * (square_size * 2 + 2)
square[0][square_size//2] = 1
i, j = 0, square_size//2
while i >= 0:
if square[i][j] == 0:
k = 1
while k <= square_size:
square[i][j] = k
if i == j:
sum_list[square_size] += k
if i + j == square_size - 1:
sum_list[square_size+1] += k
sum_list[i] += k
sum_list[j+square_size] += k
if k == square_size:
pass
elif sum_list[i] > 0 and sum_list[i] > sum_list[square_size+1]:
k = square_size - 1
elif sum_list[square_size] > 0 and sum_list[square_size] > sum_list[square_size+1]:
k = square_size - 1
elif j == square_size-1 and sum_list[j+square_size] != sum_list[square_size]:
k = square_size - 1
elif i == square_size-1 and sum_list[i] != sum_list[square_size]:
k = square_size - 1
else:
i1 = i + 1
j1 = j
if i1 == square_size:
i1 = 0
magic_square(square_size, i1, j1, sum_list)
sum_list[i] -= k
sum_list[j+square_size] -= k
if i == j:
sum_list[square_size] -= k
if i + j == square_size - 1:
sum_list[square_size+1] -= k
square[i][j] = 0
k += 1
i, j = next_position(i, j, square_size)
# 求解幻方
def next_position(i, j, n):
if i == n-1 and j == n-1:
return -1, -1
if j == n-1:
return i+1, 0
return i, j+1