题解:洛谷 B4498 画画
【题目来源】
洛谷:B4498 [GESP202603 二级] 画画 - 洛谷
【题目描述】
输入一个正整数 \(n\),你需要绘制一个 \(n\) 行 \(n\) 列的正方形,绘制规则如下:
- 正方形的四个顶点使用
+绘制; - 除顶点外,第 \(1\) 行与第 \(n\) 行使用
-绘制; - 除顶点外,第 \(1\) 列与第 \(n\) 列使用
|绘制; - 正方形内部使用
*绘制。
【输入】
一行,一个正整数 \(n\)。
【输出】
输出共 \(n\) 行,表示对应的正方形。
【输入样例】
5
【输出样例】
+---+
|***|
|***|
|***|
+---+
【核心思想】
-
问题分析:给定正整数 \(n\),需要绘制一个 \(n \times n\) 的正方形边框图案。图案由三层结构组成:四个顶点为
+,上下边框(除顶点)为-,左右边框(除顶点)为|,内部为*。本质是二维网格上的分层覆盖绘制问题。 -
算法选择:
- 分层填充法:按优先级从低到高分三层绘制——先填充内部
*,再覆盖边框-和|,最后覆盖顶点+
- 分层填充法:按优先级从低到高分三层绘制——先填充内部
-
关键步骤:
- 初始化画布:创建 \(n \times n\) 字符矩阵,全部填充为
* - 绘制边框:
- 对第 \(1\) 行和第 \(n\) 行(\(i = 1\) 或 \(i = n\)):所有列覆盖为
- - 对第 \(1\) 列和第 \(n\) 列(\(j = 1\) 或 \(j = n\)):所有行覆盖为
|
- 对第 \(1\) 行和第 \(n\) 行(\(i = 1\) 或 \(i = n\)):所有列覆盖为
- 覆盖顶点:将四个角 \((1,1)\)、\((1,n)\)、\((n,1)\)、\((n,n)\) 覆盖为
+ - 输出画布:按行输出矩阵
- 初始化画布:创建 \(n \times n\) 字符矩阵,全部填充为
-
时间/空间复杂度:
- 时间复杂度:\(O(n^2)\),初始化 \(O(n^2)\),绘制边框 \(O(n^2)\),输出 \(O(n^2)\)
- 空间复杂度:\(O(n^2)\),存储 \(n \times n\) 的画布矩阵
-
分层覆盖绘制的核心思想:
- 优先级分层:内部
*\(\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
+---+
|***|
|***|
|***|
+---+
浙公网安备 33010602011771号