2023年GESP四级图像压缩题(洛谷B3851)解析与代码实现

贾蔷
• 阅读 2

2023年GESP四级图像压缩题(洛谷B3851)解析与代码实现 一、题目解读 本题要求实现图像压缩算法,通过处理输入的灰度图像数据(以十六进制表示的像素值),将其转换为压缩后的表示形式。核心目标是通过统计灰度频率,选取前16个高频灰度值构建压缩表,并利用最小距离替换将原始像素映射到压缩表索引,从而减少数据量。题目考察对数据频率统计、排序算法及优化替换策略的理解。

二、解题思路

  1. 频率统计:读取输入数据,将每行十六进制字符串按每两位分组转换为灰度值,统计各灰度出现频率。

  2. 压缩表构建:对频率排序(高频优先,同频则灰度值小的优先),取前16个灰度值组成压缩表。

  3. 最小距离替换:遍历原始数据,计算每个灰度值与压缩表中各值的距离,选择距离最小且索引最小的替换值(避免歧义)。

  4. 输出优化:压缩表以十六进制格式输出,数据行转换为对应索引字符。

三、解题步骤

  1. 输入与初始化:

    读取图像行数n,存储原始数据到original_lines。

    创建频率统计mapfreq,初始化为空。

  2. 统计灰度频率:

    逐行处理,每两位十六进制子串转为灰度值(stoi(hex, nullptr, 16)),更新freq计数。

  3. 生成压缩表:

    将freq转为vectorgray_freq,按频率和灰度值排序(自定义cmp函数)。

    取前16个灰度值存入compressed_gray。

  4. 输出压缩表:

    使用cout << hex << setw(2) << setfill('0')格式化为两位十六进制输出。

  5. 数据压缩处理:

    遍历每行,计算每个灰度与压缩表的距离,更新最小距离和索引,将索引字符('0' + index或'A' + index - 10)拼接至compressed_line。

  6. 输出压缩数据:逐行输出compressed_line。

四、代码与注释

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <iomanip>
#include <sstream>
using namespace std;

// 自定义排序函数:按频率降序,同频则灰度值升序
bool cmp(const pair<int, int>& a, const pair<int, int>& b) {
    return a.second!= b.second? a.second > b.second : a.first < b.first;
}

int main() {
    int n;
    cin >> n;    // 输入图像行数
    vector<string> original_lines(n);  // 存储原始数据行

    // 统计灰度频率
    map<int, int> freq;
    for (int i = 0; i < n; ++i) {
        cin >> original_lines[i];
        for (size_t j = 0; j < original_lines[i].length(); j += 2) {
            // 每两位十六进制子串转换为灰度值
            string hex = original_lines[i].substr(j, 2);
            int gray = stoi(hex, nullptr, 16);
            freq[gray]++;
        }
    }

    // 排序并生成压缩表
    vector<pair<int, int>> gray_freq(freq.begin(), freq.end());
    sort(gray_freq.begin(), gray_freq.end(), cmp);
    vector<int> compressed_gray;
    for (int i = 0; i < 16; ++i) {
        compressed_gray.push_back(gray_freq[i].first);
    }

    // 输出压缩灰阶表(十六进制格式)
    for (int gray : compressed_gray) {
        cout << hex << uppercase << setw(2) << setfill('0') << gray << " ";
    }
    cout << endl;

    // 处理每行数据压缩
    for (const auto& line : original_lines) {
        string compressed_line;
        for (size_t j = 0; j < line.length(); j += 2) {
            string hex = line.substr(j, 2);
            int gray = stoi(hex, nullptr, 16);
            int min_dist = 256;  // 初始化最大距离
            int best_index = 0;  // 最佳索引

            // 查找压缩表中距离最小的灰度值索引
            for (int k = 0; k < 16; ++k) {
                int dist = abs(gray - compressed_gray[k]);
                if (dist < min_dist || (dist == min_dist && k < best_index)) {
                    min_dist = dist;
                    best_index = k;
                }
            }
            // 将索引转换为字符(0-9用数字,10-15用A-F)
            compressed_line += (best_index < 10)? char('0' + best_index) 
                : char('A' + best_index - 10);
        }
        cout << compressed_line << endl;
    }

    return 0;
}

五、总结 本算法通过灰度频率统计与最小距离替换实现了图像数据的无损压缩。关键优化点在于:

  1. 压缩表基于频率优先级,确保高频灰度用更短编码;

  2. 替换时同时考虑距离与索引顺序,避免映射歧义。

进一步优化可考虑动态调整压缩表大小或引入更高效的距离计算策略。该解法兼具逻辑清晰性与效率,适合入门级算法实践。

来源:2023年GESP四级图像压缩题(洛谷B3851)解析与代码实现

点赞
收藏
评论区
推荐文章
DaLongggggg DaLongggggg
4年前
python百题大冲关-压缩字符串
挑战介绍实现一个算法来压缩一个字符串。压缩的要求如下:需要判断压缩能不能节省空间,仅在压缩后字符串比原字符串长度更短时进行压缩。压缩的格式是将连续相同字符替换为字符数字形式,例如"AAABCCDDDD"变为"A3BC2D4"。本次挑战中,你需要在compress_str.py文件中补充函数compress的空缺部分
Stella981 Stella981
3年前
Android OpenCV(二十二):边缘检测
边缘检测什么是图像的边缘?图像的边缘是图像最基本的特征之一。所谓边缘(或边沿)是指周围像素灰度有跳跃性变化或“屋顶”变化的那些像素的集合。边缘是图像局部强度变化最明显的地方,它主要存在于目标与目标、目标与背景、区域与区域之间,因此它是图像分割依赖的重要特征。从本质上说,图像边缘是图像局部特性不连续性(灰度突变、颜色突变、纹理结构
Wesley13 Wesley13
3年前
74KB图片也高清,谷歌用神经网络打造图像压缩新算法
萧箫发自凹非寺量子位报道|公众号QbitAI还在为图像加载犯愁吗?最新的好消息是,谷歌团队采用了一种GANs与基于神经网络的压缩算法相结合的图像压缩方式HiFiC,在码率高度压缩的情况下,仍能对图像高保真还原。GAN(GenerativeAdversarialNetworks,生成式对抗网络)顾名思义
Stella981 Stella981
3年前
Android OpenCV(二十):高斯滤波
高斯滤波高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值
Stella981 Stella981
3年前
RestTemplate与Gzip压缩
Gzip是一种压缩算法,服务器经常通过这个算法来压缩响应体,再响应给客户端,从而减少数据体积,提高传输速度。客户端再通过Gzip解压缩,获取到原始的数据。因为需要压缩计算,所以会耗费额外的CPU资源。Gzip与HttpHeader对于压缩,这个行为来说,客户端与服务器都要经过协商。只有使用了同
Wesley13 Wesley13
3年前
MySQL之索引(四)
压缩索引MyISAM使用前缀压缩来减少索引的大小,从而让更多的索引可以放入内存中,这在某些情况下能极大地提高性能。默认只压缩字符串,但通过参数设置也可以对整数做压缩。MyISAM压缩每个索引块的方法是,先完全保存索引块中的第一个值,然后将其他值和第一个值进行比较得到相同前缀的字节数和剩余的不同后缀部分,把这部分存储起来即可。例如,索引块中的第
Wesley13 Wesley13
3年前
5、视频压缩编码的基本概念
视频压缩的目标是在尽可能保证视觉效果的前提下减少视频数据率。视频压缩比一般指压缩后的数据量与压缩前的数据量之比。由于视频是连续的静态图像,因此其压缩编码算法与静态图像的压缩编码算法有某些共同之处,但是运动的视频还有其自身的特性,因此在压缩时还应考虑其运动特性才能达到高压缩的目标。在视频压缩中常需用到以下的一些基本概念:一、有损和无损压缩:在视频压缩中有
Stella981 Stella981
3年前
Python OpenCV实例:图像直方图均衡化(数学公式简单实现)
coding:utf8'''直方图均衡化作用:通常用来增加图像局部对比度,尤其在图像的有用数据的对比度相当接近时,通过直方图均衡化,图像的亮度可以更好地在直方图上分布基本思想:把原始图像的直方图变换为均匀分布的形式,增加了像素灰度值的动态范围,从而增强图像的整
贾蔷 贾蔷
2星期前
2025年GESP七级等价消除(洛谷P11965)代码解析与优化策略
一、题目解读2025年GESP七级考试中的“等价消除(洛谷P11965)”问题要求统计给定字符串中满足等价条件的子串数量。所谓“等价子串”,是指子串中所有字符出现的次数均相同。题目需要高效算法解决,考验对字符串处理和状态压缩的掌握。二、解题思路采用位运算
深度学习 深度学习
4小时前
洛谷1111题解:基于Kruskal算法与并查集的最小生成树实现
一、题目解读洛谷1111题是一道经典的图论问题,要求构建一个无向图的最小生成树,并输出其最大边权值。题目核心在于通过给定的边集合,找到连接所有节点的最小权值子集,同时保证无环。这通常涉及最小生成树算法(如Kruskal)的应用,需要高效处理边权重与节点连通