题解:洛谷 P1319 压缩技术
【题目来源】
【题目描述】
设某汉字由 \(N\times N\) 的 \(0\) 和 \(1\) 的点阵图案组成。
我们依照以下规则生成压缩码。连续一组数值:从汉字点阵图案的第一行第一个符号开始计算,按书写顺序从左到右,由上至下。第一个数表示连续有几个 \(0\),第二个数表示接下来连续有几个 \(1\),第三个数再接下来连续有几个 \(0\),第四个数接着连续几个 \(1\),以此类推……
例如:以下汉字点阵图案:
0001000
0001000
0001111
0001000
0001000
0001000
1111111
对应的压缩码是\(7\ 3\ 1\ 6\ 1\ 6\ 4\ 3\ 1\ 6\ 1\ 6\ 1\ 3\ 7\) (第一个数是,其余各位表示交替表示 \(0\) 和 \(1\) 的个数,压缩码保证 \(N\times N=\) 交替的各位数之和)
【输入】
数据输入一行,由空格隔开的若干个整数,表示压缩码。
其中,压缩码的第一个数字就是 \(N\),表示这个点阵应当是 \(N\times N\) 的大小。
接下来的若干个数字,含义如题目描述所述。
【输出】
输出一个 \(N\times N\) 的 \(01\) 矩阵,表示最后的汉字点阵图(点阵符号之间不留空格)。
【输入样例】
7 3 1 6 1 6 4 3 1 6 1 6 1 3 7
【输出样例】
0001000
0001000
0001111
0001000
0001000
0001000
1111111
【核心思想】
-
问题分析:给定一个压缩码,第一个整数为边长 \(N\),后续整数交替表示连续
0和连续1的个数(第一个数表示0的个数,第二个表示1的个数,以此类推)。需要根据压缩码还原出 \(N \times N\) 的 01 矩阵,并按行输出。本质是一个游程编码(RLE)解码问题,只需按顺序输出对应数量的0和1,并在每输出 \(N\) 个字符后换行。 -
算法选择:
- 逐个数处理:读取压缩码中的所有整数,使用一个计数器
cnt记录当前已经输出的字符数。对于第 \(i\) 个数(从 1 开始计数),若 \(i\) 为奇数则输出0,若 \(i\) 为偶数则输出1,输出数量为该整数的值。每输出一个字符,cnt++,当cnt % N == 0时输出换行。 - 输入终止:由于压缩码长度不定,使用
while (cin >> x)读取直到输入结束。
- 逐个数处理:读取压缩码中的所有整数,使用一个计数器
-
关键步骤:
- 读入首数:读取第一个整数 \(N\)。
- 初始化:设置
inCnt = 0(已处理的数字个数),outCnt = 0(已输出的字符数)。 - 循环处理每个数字:
- 读取 \(x\),
inCnt++。 - 判断当前数字是代表
0还是1:若inCnt为奇数,则输出 \(x\) 个0;若为偶数,则输出 \(x\) 个1。 - 每输出一个字符,
outCnt++;若outCnt % N == 0,则输出换行。
- 读取 \(x\),
- 输出:完成所有数字处理后,矩阵已按行输出。
-
时间/空间复杂度:
- 时间复杂度:\(O(N^2)\),因为需要输出 \(N^2\) 个字符。
- 空间复杂度:\(O(1)\),只需存储当前字符和计数器。
-
模拟与游程编码:
- 交替规则:压缩码中数字交替表示
0和1的连续个数,利用inCnt的奇偶性即可判断当前应输出哪个字符。 - 换行控制:由于矩阵是按行排列的,每输出 \(N\) 个字符后必须换行,这通过
outCnt % N == 0实现。 - 输入解析:使用
while (cin >> x)可以方便地读取不定数量的整数,无需预先知道长度。 - 适用场景:这种“游程编码解码”问题常见于图像压缩或数据压缩的入门练习。
- 交替规则:压缩码中数字交替表示
【算法标签】
入门 #模拟
【代码详解】
#include <bits/stdc++.h> // 包含标准库头文件(万能头文件)
using namespace std; // 使用标准命名空间
int main()
{
int n; // 定义变量:每行输出的字符数
int inCnt = 0; // 定义变量:输入计数器(记录当前是第几个输入)
int outCnt = 0; // 定义变量:输出计数器(记录已输出的字符数)
cin >> n; // 输入每行输出的字符数
int x; // 定义变量:临时存储输入的数字
while (cin >> x) // 循环读取输入的数字
{
inCnt++; // 输入计数器加1
// 奇数位输入输出0,偶数位输入输出1
if (inCnt % 2 == 1)
{
// 输出x个0
for (int i = 1; i <= x; i++)
{
cout << 0; // 输出0
outCnt++; // 输出计数器加1
// 每输出n个字符换行
if (outCnt % n == 0)
cout << endl;
}
}
else
{
// 输出x个1
for (int i = 1; i <= x; i++)
{
cout << 1; // 输出1
outCnt++; // 输出计数器加1
// 每输出n个字符换行
if (outCnt % n == 0)
cout << endl;
}
}
}
return 0; // 程序正常结束
}
【运行结果】
7 3 1 6 1 6 4 3 1 6 1 6 1 3 7
0001000
0001000
0001111
0001000
0001000
0001000
1111111
浙公网安备 33010602011771号