CCF-CSP真题202212-3JPEG解码(Java满分题解)

1.题目详情

2.输入输出说明

3.思路

(1)子任务中有20分的得分点是填充扫描数据后的矩阵,后续与量化矩阵相乘、离散余弦逆变换、以及加上数字128的操作都较为简单。所以我们的重心就在如何把填充的数据放入到矩阵中。
(2)观察图中,在次对角线(一般称主对角线为从左上角到右下角,次对角线为右上角到左下角)的上方,当遇到边界情况时x和y的值变化情况就要交换一下。所以我们在次对角线上方遇到x或y有一个为0时说明碰到边界情况了。此时我们定义一个临时变量用来计数,当第一次遇到时在不为0的方向继续加一。同时当遇到边界后也要定义一个变量给他赋值为0或1代表x和y不同的变化情况。
(3)当在次对角线下方时我们可以声明一个方法用来处理这种情况。当然在次对角线上方和下方分别定义一个方法是最好的。不过传入和返回的变量都比较多,注意变量的声明位置和处理函数的返回情况是非常重要的。
(4)其他的比如在离散余弦变换、离散变化余弦中的一些条件可以直接封装为方法,直接调用使用即可。并且由于题目要根据输入的不同值来判读最终输出哪个矩阵。我们把输出矩阵也封装为一个方法,直接传入要输出的矩阵名将其进行输出即可。

提示:第三题一般涉及的处理的细节很多很杂,但又不涉及很难得算法。只要耐下心来,处理好每一个步骤,就可以拿下第三题的分数。

Java代码如下(100分)

import java.util.Scanner;
public class Main {
    public static void print(double[][] arr){
        for(int i = 0;i<=7;i++){
            for(int j = 0;j<=7;j++){
                if(j != 7){
                    System.out.print((int)arr[i][j] + " ");
                }else{
                    System.out.print((int)arr[i][j]);
                }
            }
            System.out.println();
        }
    }
    public static double getFunction(int k){
        if(k == 0) {
            return Math.sqrt((double)1/2);
        }else{
            return 1;
        }
    }
    public static double travel(double[][] arr,int m,int n){
        double sum = 0.0;
        for(int i = 0;i<=7;i++){
            for(int j = 0;j<=7;j++){
                double k1 = getFunction(i);
                double k2 = getFunction(j);
                sum += k1*k2*arr[i][j]*Math.cos((Math.PI/(double)8)*(m+1/(double)2)*i)*Math.cos((Math.PI/(double)8)*(n+1/(double)2)*j);
            }
        }
        return sum/(double)4;
    }
    public static int[] behindData(int x,int y,int out,int flag){
        //int flag = 0;
        // count = 35
        if(x != 7 && y == 7 && out ==0){
            x += 1;
            flag = 1;
            out++;
        }else if(x == 7 && y !=7 && out ==0){
            y += 1;
            flag = 0;
            out++;
        }else{
            out = 0;
            if(flag == 0){
                x -= 1;
                y += 1;
            }else{
                x += 1;
                y -= 1;
            }
        }
        return new int[]{x,y,out,flag};
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double[][] Q = new double[8][8];
        //量化矩阵Q的输入
        for(int i = 0;i<Q.length;i++){
            for (int j = 0; j < Q[i].length; j++) {
                Q[i][j] = sc.nextInt();
            }
        }
        //填充矩阵
        double[][] scMatrix = new double[8][8];
        //读入扫描的个数
        int scNum = sc.nextInt();
        //读入要输出的结果情况
        int T = sc.nextInt();
        int count = 0;
        int flag = 0;
        int temp_x = 0;
        int temp_y = 0;
        int out = 0;
        while(count < scNum){
//            00  1次了 35 35次
            if(count == 35){
                scMatrix[temp_x][temp_y] = sc.nextInt();
                count++;
                continue;
            }
            if(count > 35){
                int temp[] = behindData(temp_x,temp_y,out,flag);
                temp_x = temp[0];
                temp_y = temp[1];
                out = temp[2];
                flag = temp[3];
                scMatrix[temp_x][temp_y] = sc.nextInt();
//                System.out.print(temp_x + "" + temp_y + " ");
                count++;
                continue;
            }else{
                scMatrix[temp_x][temp_y] = sc.nextInt();
            }
            count++;
            //若为原点则进行特殊处理
            if(temp_y==0 && temp_x ==0){
                temp_y += 1;
                continue;
            }
            //第二次也进行特殊处理
            if(temp_x ==0 && temp_y ==1){
                temp_x += 1;
                temp_y -= 1;
                continue;
            }
            if(temp_y == 0 && temp_x != 0 && out==0){
                temp_x += 1;
                flag = 0;
                out ++;
            }else if(temp_x == 0 && temp_y != 0 && out == 0){
                temp_y += 1;
                flag = 1;
                out++;
            }else{
                out = 0;
                if(flag == 0){
                    temp_y += 1;
                    temp_x -= 1;
                }else{
                    temp_x += 1;
                    temp_y -= 1;
                }
            }
        }
        //量化矩阵乘扫描数据的矩阵结果
        double[][] res1 = new double[8][8];
        double[][] travelMatrix = new double[8][8];
        double res2[][] = new double[8][8];
        for(int i = 0;i<=7;i++){
            for(int j = 0;j<=7;j++){
                res1[i][j] = scMatrix[i][j] * Q[i][j];
            }
        }
        //将矩阵每个元素都加上128,并取最近的整数(四舍五入)。
        for(int i = 0;i<=7;i++){
            for(int j = 0;j<=7;j++){
                travelMatrix[i][j] = travel(res1,i,j);
                double temp = Math.round(travelMatrix[i][j] + 128);
                if(temp > 255){
                    res2[i][j] = 255;
                }else if(temp < 0){
                    res2[i][j] = 0;
                }else{
                    res2[i][j] = temp;
                }
            }
        }
        //最后进行打印输出
        if(T == 0) {
            print(scMatrix);

        }else if( T == 1){
            print(res1);
        }else{
            print(res2);
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北洋的霞洛

觉得不确可以给个鼓励小费

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值