TB椰程 TypeBuddy 打字搭子

2023-06 · 4级 · 图像压缩

GESP 标程 · 考级真题 · 代码 · cpp · 难度 5/5 · 共 2054 字

CCF 原卷官方标程 · 字符串、结构体与类、位运算、图论 · 本地编译通过

  • 2023-06
  • 字符串

正文

// GESP 2023-06 C++ 4级 编程题 2 · 图像压缩
// 原题:https://oj.yecheng.tv/p/gs2306l4p2
// 官方原卷:https://gesp.ccf.org.cn/101/attach/1553241699516448.pdf
// 题意:图像是由很多的像素点组成的。
// 知识点:字符串、结构体与类、位运算、图论
// 参考程序:CCF 原卷官方标程,PDF 抽取后已去行号;本地编译核验通过,供打字练习
// 原卷样例验证:样例验证 1/1 通过
//
#include <iostream>
#include <cstring>
using namespace std;
int image[20][20];
int cpimg[20][20];
int his[256];
int color[16];
// 一位十六进制字符转换为数字
int trans(char a) {
    if (a <= '9')
        return (a - '0');
    return (a - 'A' + 10);
}
// 一位十六进制数字转换为字符
char itrans(int n) {
    if (n >= 10)
        return (char)(n - 10 + 'A');
    return (char)(n + '0');
}
// 寻找离 c最近的灰阶
int compress(int c) {
    int dis = 256, res = -1;
    for (int i = 0; i < 16; i++) {
        int d = c - color[i];
        if (d < 0)
            d = -d;
        if (d < dis) {
            dis = d;
            res = i;
        }
    }
    return res;
}
int main() {
    int N = 0, M = 0;
    cin >> N;
    // 灰阶计数,初始化为 0
    for (int i = 0; i < 256; i++)
        his[i] = 0;
    // 输入图像,并对灰阶计数
    for (int i = 0; i < N; i++) {
        char line[50];
        cin >> line;
        M = strlen(line) / 2;
        for (int j = 0; j < M; j++) {
            int c = trans(line[j * 2]) * 16 + trans(line[j * 2 + 1]);
            image[i][j] = c;
            his[c]++;
        }
    }
    // 选取出现次数最多的 16 个灰阶
    for (int c = 0; c < 16; c++) {
        int max = -1, max_id = -1;
        for (int i = 0; i < 256; i++)
            if (his[i] > max) {
                max = his[i];
                max_id = i;
            }
        color[c] = max_id;
        his[max_id] = -1;
    }
    // 将 image 的灰阶压缩为 cpimg
    for (int i = 0; i < N; i++)
        for (int j = 0; j < M; j++)
            cpimg[i][j] = compress(image[i][j]);
    // 输出选取的 16 个灰阶
    for (int c = 0; c < 16; c++)
        cout << itrans(color[c] / 16) << itrans(color[c] % 16);
    cout << endl;
    // 输出压缩后的图像
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++)
            cout << itrans(cpimg[i][j]);
        cout << endl;
    }
    return 0;
}

GESP 标程 · 考级真题的其它内容

打字首页 · 英语学习中心 · 词库画廊 · 编程打字 · 指法入门 · 天梯榜 · 数据分析 · 班级课堂 · 关于我们
椰程 TypeBuddy 打字搭子 —— 键盘指法练习 · 单词记忆 · 班级课堂 · 在线 PK