100. 2017年蓝桥杯省赛 - 九宫幻方(困难)- 暴力搜索
100. 九宫幻方(暴力搜索)
2017年蓝桥杯省赛 - 九宫幻方(困难)
标签:2017
暴力
省赛
搜索
题目描述
小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将 1~9 不重复的填入一个 3*3 的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。
三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:“二四为肩,六八为足,左三右七,戴九履一,五居其中”,通过这样的一句口诀就能够非常完美的构造出一个九宫格来。
4 9 2
3 5 7
8 1 6
有意思的是,所有的三阶幻方,都可以通过这样一个九宫格进行若干镜像和旋转操作之后得到。现在小明准备将一个三阶幻方(不一定是上图中的那个)中的一些数抹掉,交给邻居家的小朋友来进行还原,并且希望她能够判断出究竟是不是只有一个解。
而你呢,也被小明交付了同样的任务,但是不同的是,你需要写一个程序。
输入描述
输入仅包含单组测试数据。
每组测试数据为一个 3*3 的矩阵,其中为 0 的部分表示被小明抹去的部分。
给出的矩阵至少能还原出一组可行的三阶幻方。
输出描述
如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出"Too Many"(不包含引号)。
输入输出样例
示例:
输入
0 7 2
0 5 0
0 3 0
输出
6 7 2
1 5 9
8 3 4
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
算法思路
题目要求根据给定的部分三阶幻方恢复完整的三阶幻方,并且判断是否只有唯一的解。具体解法的核心思路是,首先考虑到所有的三阶幻方都是通过旋转和镜像变换获得的,因此我们可以首先预定义所有可能的三阶幻方,并尝试恢复其中一个符合给定部分的幻方。如果存在多个符合条件的解,则输出"Too Many"。
步骤分析
-
定义所有可能的三阶幻方
三阶幻方的所有变换形式可以通过旋转和镜像操作从一个基本的幻方得到,包括以下操作步骤:
旋转:不旋转、顺时针90°(或逆时针270°)、顺时针180°(或逆时针180°)、顺时针270°(或逆时针90°)
镜像:不镜像、垂直镜像、水平镜像
由上图可知,三阶幻方共有8种排列可能,构造二维列表如下:
mf = ['492357816', '816357492', '438951276', '834159672','294753618', '618753294', '276951438', '672159834', ]
-
输入处理
输入一个 3x3 的矩阵,其中 0 表示某些数字被抹去了,其他位置是已经给定的数字。我们将其按行读取并存储。 -
匹配幻方
对于每一个可能的三阶幻方形式,判断其是否符合给定部分的数字。检查的过程是:对于已给定的数字,如果该位置的数字与当前幻方的数字不一致,则该幻方形式不符合。 -
判断唯一性
如果有多个符合条件的幻方形式,则输出"Too Many"。如果只有一个符合的幻方,则输出该幻方。
代码实现
mf = ['492357816', '816357492', '438951276', '834159672','294753618', '618753294', '276951438', '672159834'
]s = ''
for _ in range(3): # 输入九宫幻方s += ''.join(input().split())sl = []
for i in range(8): # 遍历8种可能排列n = 0for j in range(9): # 遍历9个数字if s[j] != '0': # 跳过空格if mf[i][j] != s[j]: # 若数字不匹配,则排列无效breakelse:n += 1else:n += 1if n == 9:sl.append(i) # 记录可能的排列breakif len(sl) > 1:print("Too Many") # 若有多种可能,输出 Too Many
else:t = sl[0] # 确定唯一的排列for j in range(0, len(mf[t]), 3):print(' '.join(mf[t][j:j + 3]))
复杂度分析
- 时间复杂度: O ( 1 O(1 O(1)(由于固定循环次数)
- 空间复杂度: O ( 1 ) O(1) O(1)(由于存储空间固定)