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);
}
}
}