问题描述
小明为某机构设计了一个十字型的徽标(并非红十字会啊)。
输入:
一个正整数n(n< 30)表示要求打印图形的层数。
输出:
对应包围层数的该标志(中心固定)。
示例
输入:
1
输出:
解决方案
这道题打印的是一个对称图形,而且对称轴很多,那么就可以利用图形的对称性进行思考。这里先上下对折,然后左右对折,最后45度角对折,得到一个直角三角形。如下图所示:
图 2.1变化过程
现在可以对被分成八份的图形(也就是直角三角形)进行大致的分析:
(注:行列从0开始)
前面两行都为(.)
偶数行的最后三个都为($)
偶数列大多都为($),除了特殊的几个位置(列值刚好比行值小1的时候)
其他都是(.)
根据这四个规律就可以打印分成八份的图形(直角三角形),再根据对称性就可以打印出题目要求的图形。但是,输出的时候是一行一行的输出的,如果成全是(.)的矩阵再遍历一个一个填入($)的话时间和空间复杂度就很大了。所以可以先把除直角三角形外的其他部分按照对称性先转换成直角三角形后按前面四个规律直接输出。
题目代码:
def aa(i, j, n): # 利用上下对称转换 if i >= (m 1)/2: i = m-1-i # 利用左右对称转换 if j >= (m 1)/2: j = m-1-j # 利用45度角对称转换 if j > i: i, j = j, i # 四个角2*2的都为(.)的矩形 if i <= 1 and j <= 1: return '.' # 偶数行最后的三个$和偶数列前面几个$ elif (i % 2 == 0 and j 2 >= i) or (j % 2 == 0 and j 1 != i): return '$' # 其他的都是点 else: return '.' n = int(input())# 长宽的值m = n*4 5for i in range(m): for j in range(m): print(aa(i, j, n), end='') # 注意换行 print('') |
---|
注意:上面三个利用对称关系转换的代码是有一定的次序的,前两个可以随意更换位置,但第三个必须放在前两个后面,否则后面的代码全部都要进行更换。
结语
基本上绝大部分类似这种输出一个由几个字符组成的对称图形的题都可以先利用对称性把图形‘缩小’,这样可以很容易找到一定的规律并且这种规律大多都不繁杂。当然这种题也不一定要利用对称性把图形‘缩小’到最小,可能中间的某个图形就能找到十分简单的规律,或者直接寻找整个图形的某些规律。
END
编 辑 | 王楠岚
责 编 | 周茂林
where2go 团队