题解:洛谷 B4360 画布剪裁
【题目来源】
洛谷:B4360 [GESP202506 四级] 画布裁剪 - 洛谷
【题目描述】
小 A 在高为 \(h\) 宽为 \(w\) 的矩形画布上绘制了一幅画。由于画布边缘留白太多,小 A 想适当地裁剪画布,只保留画的主体。具体来说,画布可以视为 \(h\) 行 \(w\) 列的字符矩阵,其中的字符均为 ASCII 码位于 \(33∼126\) 之间的可见字符,小 A 只保留画布中由第 \(x_1\) 行到第 \(x_2\) 行、第 \(y_1\) 列到第 \(y_2\) 列构成的子矩阵。
小 A 将画布交给了你,你能帮他完成画布的裁剪吗?
【输入】
第一行,两个正整数 \(h,w\),分别表示画布的行数与列数。
第二行,四个正整数 \(x_1,x_2,y_1,y_2\),表示保留的行列边界。
接下来 \(h\) 行,每行一个长度为 \(w\) 的字符串,表示画布内容。
【输出】
输出共 \(x_2−x_1+1\) 行,每行一个长度为 \(y_2−y_1+1\) 的字符串,表示裁剪后的画布。
【输入样例】
3 5
2 2 2 4
.....
.>_<.
.....
【输出样例】
>_<
【核心思想】
-
问题分析:给定一个 \(h \times w\) 的字符矩阵,需要输出由第 \(x_1\) 行到第 \(x_2\) 行、第 \(y_1\) 列到第 \(y_2\) 列构成的子矩阵。这是一个矩阵子区域提取问题,核心在于正确读取输入并按指定行列范围输出。
-
算法选择:
- 二维数组存储:将画布内容存入二维字符数组
- 范围遍历输出:按指定行列边界遍历并输出对应字符
-
关键步骤:
- 读入数据:读取 \(h, w\) 和裁剪边界 \(x_1, x_2, y_1, y_2\)
- 读取画布:遍历 \(i\) 从 \(1\) 到 \(h\),\(j\) 从 \(1\) 到 \(w\),读入 \(a[i][j]\)
- 输出子矩阵(\(i\) 从 \(x_1\) 到 \(x_2\)):
- \(j\) 从 \(y_1\) 到 \(y_2\):输出 \(a[i][j]\)
- 每行结束后输出换行
-
时间/空间复杂度:
- 时间复杂度:\(O(h \cdot w)\),读取整个画布并输出子区域
- 空间复杂度:\(O(h \cdot w)\),存储完整画布
-
矩阵子区域提取的核心思想:
- 坐标映射:输入的行列坐标直接对应数组下标,无需复杂转换,按给定范围直接遍历即可
- 逐行输出:外层循环控制行,内层循环控制列,每行结束后换行,保持矩阵的二维结构
- 边界安全性:题目保证输入边界合法,无需额外的越界检查
- 适用于基础矩阵操作、子区域提取类入门问题
【算法标签】
入门 #字符串入门
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 105; // 定义网格最大尺寸
int h, w; // 网格的行数和列数
char a[N][N]; // 存储网格字符的二维数组
int x1, x2, y1, y2; // 定义要输出的子网格范围
int main()
{
// 输入网格的行数和列数
cin >> h >> w;
// 输入要输出的子网格范围(左上角和右下角坐标)
cin >> x1 >> x2 >> y1 >> y2;
// 输入网格数据
for (int i = 1; i <= h; i++)
for (int j = 1; j <= w; j++)
cin >> a[i][j];
// 输出指定子网格范围内的内容
for (int i = x1; i <= x2; i++)
{
for (int j = y1; j <= y2; j++)
cout << a[i][j]; // 输出当前字符
cout << endl; // 每行结束后换行
}
return 0;
}
【运行结果】
3 5
2 2 2 4
.....
.>_<.
.....
> _ <
浙公网安备 33010602011771号