我们需要绘制一个 n×n 的字符菱形,其中 n 为大于 1 的奇数。菱形的四个顶点分别位于四条边的正中间:
相邻顶点之间用 # 连接,形成菱形的四条边。其余位置用 . 填充。
以 n=5 为例,菱形图案如下:
..#..
.#.#.
#...#
.#.#.
..#..
可以观察到,所有 # 恰好位于以正方形中心为原点、曼哈顿距离为 k=⌊n/2⌋ 的位置上。
在 n×n 的网格中,定义中心点的坐标为 (c,c),其中 c=2n+1(行列编号从 1 开始)。
对于网格中的任意位置 (i,j),它到中心点的曼哈顿距离为:
当 d=k(其中 k=2n−1=⌊n/2⌋)时,该位置正好落在菱形的边上,应输出 #;否则输出 .。
完整遍历所有行 i 和列 j,依次判断并输出即可。
#;否则输出 .。下面是基于上述思路的 C++ 实现,代码已包含详细注释。
cpp1#include <iostream> 2#include <cstdlib> // 提供 abs 函数 3using namespace std; 4 5int main() { 6 int n; 7 cin >> n; 8 int k = n / 2; // 菱形半径 9 // 外层循环:行 10 for (int i = 1; i <= n; i++) { 11 // 内层循环:列 12 for (int j = 1; j <= n; j++) { 13 // 计算当前点 (i, j) 到中心 (k+1, k+1) 的曼哈顿距离 14 // 中心坐标为 k+1 是因为行列编号从 1 开始,而 k = (n-1)/2 15 if (abs(k - i + 1) + abs(k - j + 1) == k) 16 cout << '#'; 17 else 18 cout << '.'; 19 } 20 cout << endl; // 换行 21 } 22 return 0; 23}
k = n / 2:由于 n 是奇数,n/2 正好等于 (n−1)/2,即菱形的半边长(从中心到顶点的曼哈顿距离)。abs(k - i + 1) + abs(k - j + 1):计算 (i,j) 到中心点 (k+1,k+1) 的曼哈顿距离。当距离恰好等于 k 时,说明该位置在菱形的边上。cout 逐个输出字符,最终形成菱形图案。算法使用了两层循环遍历 n×n 个格子,每个格子进行常数次运算,因此时间复杂度为 O(n2)。
题目中 n 最大仅为 29,O(n2) 的复杂度完全可以在 1 秒内轻松运行完毕。
本题本质上是根据曼哈顿距离绘制菱形边框。将几何图形的对称性转化为数学表达式,是解决此类字符画问题的重要方法。理解“曼哈顿距离等于定值”对应菱形这一结论后,即可轻松写出简短且高效的代码。