202509-菱形(luogu-B4412)

202509-菱形(luogu-B4412)

GESP C++ 2025年9月二级真题,多层循环练习,难度★✮☆☆☆。

luogu-B4412 [GESP202509 二级] 菱形

题目要求

题目描述

小 A 想绘制一个菱形。具体来说,需要绘制的菱形是一个 nnnn 列的字符画,nn 是一个大于 11 的奇数。菱形的四个顶点依次位于第 11 行、第 11 列、第 nn 行、第 nn 列的正中间,使用 # 绘制。相邻顶点之间也用 # 连接。其余位置都是 .

例如,一个 5555 列的菱形字符画是这样的:

..#..
.#.#.
#...#
.#.#.
..#..

给定 nn,请你帮小 A 绘制对应的菱形。

输入格式

一行,一个正整数 nn

输出格式

输出共 nn 行,表示对应的菱形。

输入输出样例 #1

输入 #1
3
输出 #1
.#.
#.#
.#.

输入输出样例 #2

输入 #2
9
输出 #2
....#....
...#.#...
..#...#..
.#.....#.
#.......#
.#.....#.
..#...#..
...#.#...
....#....

说明/提示

对于所有测试点,保证 3n293 \leq n \leq 29 并且 nn 为奇数。


题目分析

本题要求输出一个 n×nn \times n 的“菱形”图案,nn 为奇数。每行每列只包含字符 #.# 组成菱形的边界,其余为 .

核心思路

  1. 确定中心位置
    由于 nn 为奇数,中心行为 mid=n+12\text{mid} = \frac{n+1}{2},中心列同理。

  2. 分行讨论

    • 首行和末行:只有中心列为 #,其余为 .
    • 上半部分(第 11 行到第 mid1\text{mid}-1 行):每行有两个 #,分别在:
    {左斜线列号=midi+1右斜线列号=mid+i1 \begin{cases} \text{左斜线列号} = \text{mid} - i + 1 \\ \text{右斜线列号} = \text{mid} + i - 1 \end{cases}
    • 中间行(第 mid\text{mid} 行):只有首列和末列为 #
    • 下半部分(第 mid+1\text{mid}+1 行到第 nn 行):与上半部分对称,# 分别在:
    {左斜线列号=imid+1右斜线列号=ni+mid \begin{cases} \text{左斜线列号} = i - \text{mid} + 1 \\ \text{右斜线列号} = n - i + \text{mid} \end{cases}
  3. 遍历输出
    双重循环枚举每个位置,判断是否为 #,否则输出 .

复杂度分析

  • 时间复杂度 O(n2)O(n^2),空间复杂度 O(1)O(1)n29n \leq 29 时完全可行。

细节注意

  • 行列编号从 11 开始更便于公式表达。
  • 输出时每行末尾不要多余空格。

本题考查二维模拟与对称性分析,理解行列与中心的关系是关键。


示例代码

#include <iostream>

int main() {
    int n;
    std::cin >> n;                    // 读入菱形边长(奇数)
    int mid = (n + 1) / 2;              // 计算中心行/列位置
    for (int i = 1; i <= n; i++) {    // 逐行绘制
        for (int j = 1; j <= n; j++) { // 逐列绘制
            if (i == 1 || i == n) {    // 首行或末行:仅中心位置输出 #
                if (j == mid) {
                    std::cout << "#";
                } else {
                    std::cout << ".";
                }
            } else if (i < mid) {      // 上半部分:对称的两条斜线
                // 上半部分:左斜线列号 = 中心列 - 当前行 + 1,右斜线列号 = 中心列 + 当前行 - 1
                if (j == mid - i + 1 || j == mid + i - 1) {
                    std::cout << "#";
                } else {
                    std::cout << ".";
                }
            } else {                   // 下半部分:对称的两条斜线
                // 左斜线列号 = 当前行 - 中心行 + 1,右斜线列号 = 总列数 - 当前行 + 中心行
                if (j == i - mid + 1 || j == n - i + mid) {
                    std::cout << "#";
                } else {
                    std::cout << ".";
                }
            }
        }
        std::cout << "\n";             // 换行进入下一行
    }
    return 0;
}

本文由coderli.com原创,按照CC BY-NC-SA 4.0 进行授权

所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code

luogu-”系列题目可在 洛谷题库 在线评测。

bcqm-”系列题目可在 编程启蒙题库 在线评测。

GESP/CSP 认证学习微信公众号
GESP/CSP 认证学习微信公众号
最后更新于