202212-3 CCF JPEG 解码 满分题解(超详细注释代码) + 两种解题思路(z字形模拟 / 打表法)

问题描述

解题思路

202212-3 CCF JPEG 解码 满分题解(超详细注释代码) + 两种解题思路(z字形模拟 / 打表法)_第1张图片
202212-3 CCF JPEG 解码 满分题解(超详细注释代码) + 两种解题思路(z字形模拟 / 打表法)_第2张图片
除了填充那一步,其余的根据题目模拟就行,代码很清晰,可以看一下代码


代码实现

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
int L[8][8];
int M[8][8];

int main()
{
    for (int i = 0; i < 8; i ++)
        for (int j = 0; j < 8; j ++)
            scanf("%d", &L[i][j]); //读入量化矩阵
    memset(M, 0, sizeof(M)); //初始化M数组

    int n, op; 
    scanf("%d%d", &n, &op);
    int t[64]; //存储输入的n + 1个数
    memset(t, 0, sizeof(t));
    for (int i = 0; i < n; i ++) scanf("%d", &t[i]);

    int i = 0, j = 1; //从(0, 1)开始z字形遍历
    int cnt = 0; //记录已经填充了几个数,cnt < n
    M[0][0] = t[cnt ++]; //填入(0, 0)这个点
    bool up = false; //up标志位记录当前是往右上走还是左下走
    while (1)
    {
        if (!up) //往左下走
        {
            while (i < 8 && j >= 0 && cnt < n) //i和j没越界并且当前填充个数小于n
            {
                M[i][j] = t[cnt ++]; //填充
                j --; //左
                i ++; //下
            }
            if (cnt == n) break; //已经填充完了,剩下的是0,不用填充了
            if (i == 8) //在最下面一行越界了,应该要往右水平走一
            {
                i --; //i往上一行,为第7行
                j += 2; //
                if (i == 7 && j == 7) //是最后一格
                {
                    M[i][j] = t[cnt ++]; //填充
                    break;
                }
            }
            else if (j < 0)  j = 0; //左边界越界
            up = true; //改方向
            continue;
        }
        else //和上面类似,反一下
        {
            while (i >= 0 && j < 8 && cnt < n)
            {
                M[i][j] = t[cnt ++];
                i --;
                j ++;
            }
            if (cnt == n) break;
            if (j == 8)
            {
                j --;
                i += 2;
            }
            else if (i < 0)  i = 0;
            up = false;
            continue;
        }
    }

    if (op == 0) //任务0
    {
        for (int i = 0; i < 8; i ++)
        {
            for (int j = 0; j < 8; j ++)
            {
                cout << M[i][j] << " "; //输出填充后的矩阵
            }
            cout << endl;
        }
        return 0;
    }
    if (op == 1) //任务1
    {
        for (int i = 0; i < 8; i ++)
        {
            for (int j = 0; j < 8; j ++)
            {
            	M[i][j] *= L[i][j];
                cout << M[i][j] << " "; //输出填充矩阵 * 量化矩阵
            }
            cout << endl;
        }
        return 0;
    }

	//任务2
    if (op == 2)
    {
        double sum[8][8]; //记录M‘ij

        memset(sum, 0, sizeof(sum));

        for (int i = 0; i < 8; i ++)
        {
            for (int j = 0; j < 8; j ++)
            {
                double res = 0;
                for (int u = 0; u < 8; u ++)
                {
                    for (int v = 0; v < 8; v ++)
                    {
                        double t = 1;
                        if (M[u][v] == 0) continue; //答案为0,不用算了
						//照着公式看就行
                        if (u == 0 && v == 0) t *= 0.5; 
                        else if (u == 0 || v == 0) t *= sqrt(0.5);

                        t *= M[u][v];

                        double num1 = 1, num2 = 1;
                        if (1)
                        {
                            num1 *= (i + 0.5);
                            num1 *= u;
                            num1 *= acos(-1);
                            num1 /= 8;
                        }
                        if (1)
                        {
                            num2 *= (j + 0.5);
                            num2 *= v;
                            num2 *= acos(-1);
                            num2 /= 8;
                        }
                        num1 = cos(num1);
                        num2 = cos(num2);
                        t *= num1;
                        t *= num2;
                        res += t;
                    }
                }
                sum[i][j] = res / 4;
            }
        }

        for (int i = 0; i < 8; i ++)
        {
            for (int j = 0; j < 8; j ++)
            {
                int x = round(sum[i][j] + 128); //加128取整
                if (x < 0) cout << 0 << " ";
                else if (x > 255) cout << 255 << " ";
                else cout << x << " ";
                //cout << sum[i][j] << " ";
            }
            cout << endl;
        }
    }
    return 0;
}

你可能感兴趣的:(ccf历年真题,c++,CCFCSP,JPEG解码,满分题解,大模拟)