题解:洛谷 B4498 画画

【题目来源】

洛谷:B4498 [GESP202603 二级] 画画 - 洛谷

【题目描述】

输入一个正整数 \(n\),你需要绘制一个 \(n\)\(n\) 列的正方形,绘制规则如下:

  • 正方形的四个顶点使用 + 绘制;
  • 除顶点外,第 \(1\) 行与第 \(n\) 行使用 - 绘制;
  • 除顶点外,第 \(1\) 列与第 \(n\) 列使用 | 绘制;
  • 正方形内部使用 * 绘制。

【输入】

一行,一个正整数 \(n\)

【输出】

输出共 \(n\) 行,表示对应的正方形。

【输入样例】

5

【输出样例】

+---+
|***|
|***|
|***|
+---+

【核心思想】

  1. 问题分析:给定正整数 \(n\),需要绘制一个 \(n \times n\) 的正方形边框图案。图案由三层结构组成:四个顶点为 +,上下边框(除顶点)为 -,左右边框(除顶点)为 |,内部为 *。本质是二维网格上的分层覆盖绘制问题。

  2. 算法选择

    • 分层填充法:按优先级从低到高分三层绘制——先填充内部 *,再覆盖边框 -|,最后覆盖顶点 +
  3. 关键步骤

    • 初始化画布:创建 \(n \times n\) 字符矩阵,全部填充为 *
    • 绘制边框
      • 对第 \(1\) 行和第 \(n\) 行(\(i = 1\)\(i = n\)):所有列覆盖为 -
      • 对第 \(1\) 列和第 \(n\) 列(\(j = 1\)\(j = n\)):所有行覆盖为 |
    • 覆盖顶点:将四个角 \((1,1)\)\((1,n)\)\((n,1)\)\((n,n)\) 覆盖为 +
    • 输出画布:按行输出矩阵
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n^2)\),初始化 \(O(n^2)\),绘制边框 \(O(n^2)\),输出 \(O(n^2)\)
    • 空间复杂度:\(O(n^2)\),存储 \(n \times n\) 的画布矩阵
  5. 分层覆盖绘制的核心思想

    • 优先级分层:内部 * \(\to\) 边框 -/| \(\to\) 顶点 +,后绘制的覆盖先绘制的,确保顶点 + 不会被边框字符覆盖
    • 行列对称性:利用正方形的对称性,通过判断 \(i\) 是否为边界行或 \(j\) 是否为边界列来统一处理,避免逐个坐标硬编码
    • 先填充后覆盖:先将整个矩阵置为 *,再对特殊位置进行覆盖,避免了复杂的条件分支判断(如判断"是否在边界且不是顶点")
    • 边界条件的简洁表达:使用 if (i == 1 || i == n)if (j == 1 || j == n) 分别处理横纵边框,逻辑清晰且互不干扰
    • 适用于规则几何图形的分层绘制、矩阵边框生成、字符画构造等基础图形处理问题

【算法标签】

入门 #语法基础

【代码详解】

#include <bits/stdc++.h>  // 包含所有标准库头文件
using namespace std;       // 使用标准命名空间

const int N = 105;  // 定义常量N,表示数组的最大尺寸
int n;              // 变量n,表示实际使用的尺寸
char a[N][N];       // 定义二维字符数组a,用于存储图案

int main()  // 主函数入口
{
    cin >> n;  // 输入n,表示图案的尺寸

    // 第一阶段:初始化整个数组为'*'
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            a[i][j] = '*';  // 将所有位置初始化为星号
        }
    }

    // 第二阶段:绘制边框
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            // 如果是第一行或最后一行,设置为'-'(横线)
            if (i == 1 || i == n)
            {
                a[i][j] = '-';
            }

            // 如果是第一列或最后一列,设置为'|'(竖线)
            if (j == 1 || j == n)
            {
                a[i][j] = '|';
            }
        }
    }

    // 第三阶段:设置四个角的字符为'+'
    a[1][1] = '+';      // 左上角
    a[1][n] = '+';      // 右上角
    a[n][1] = '+';      // 左下角
    a[n][n] = '+';      // 右下角

    // 第四阶段:输出整个图案
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cout << a[i][j];  // 输出当前位置的字符
        }
        cout << endl;  // 每输出完一行后换行
    }

    return 0;  // 程序正常结束
}

【运行结果】

5
+---+
|***|
|***|
|***|
+---+
posted @ 2026-07-01 19:09  团爸讲算法  阅读(31)  评论(0)    收藏  举报