题解:P13899 [CSPro 28] JPEG 解码
ILearnedSomeCoding · · 题解
题目意思
要写一个很高级的JPEG解码器。
有三个步骤:
- 先斜着填充矩阵。
- 量化(其实就是把所有的数都乘上一个相对应的数值)。
- 进行离散余弦逆变换。
- 将矩阵中的每个元素都加上
128 ,并取最接近的整数(四舍五入)。如果得到的整数大于255 ,则取255 ;如果得到的整数小于0 ,则取0 。
先输入量化矩阵(就是填充完了要乘的)那个矩阵。
然后输入操作类型,
这个离散余弦逆变换怎么做呢?我们看题:
其中
这个就是个大模拟,看起来挺吓唬人的,但是其实就是这样的代码:
// Mi 数组是 M 矩阵, Mp 是 M' 矩阵
const ld PI = acosl(-1.0L);
alpha[0] = sqrtl(0.5L);
for(int u = 1;u < 8;u++){
alpha[u] = 1.0L;
}
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
for(int u = 0;u < 8;u++){
for(int v = 0;v < 8;v++){
Mp[i][j] += 0.25 * alpha[u] * alpha[v] * Mi[u][v] * cosl(PI / 8 * (i + 0.5) * u) * cosl(PI / 8 * (j + 0.5) * v);
}
}
}
}
然后只要别忘了加上
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
int Q[8][8], Mi[8][8];
ld M[8][8], Mp[8][8], alpha[8];
int res[8][8], posx[64], posy[64], shuru[64];
int main(){
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
cin >> Q[i][j];
}
}
int n;
cin >> n;
int T;
cin >> T;
for(int i = 0;i < n;i++){
cin >> shuru[i];
}
int cnt = 0;
for(int s = 0;s <= 14;s++){
if(s % 2 == 0){
for(int i = s;i >= 0;i--){
int j = s - i;
if(0 <= i && i < 8 && 0 <= j && j < 8){
posx[cnt] = i;
posy[cnt] = j;
cnt++;
}
}
}else{
for(int i = 0;i <= s;i++){
int j = s - i;
if(0 <= i && i < 8 && 0 <= j && j < 8){
posx[cnt] = i;
posy[cnt] = j;
cnt++;
}
}
}
}
for(int k = 0;k < n;k++){
int x = posx[k];
int y = posy[k];
Mi[x][y] = shuru[k];
}
if(T == 0){
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
if(j) cout << ' ';
cout << Mi[i][j];
}
cout << endl;
}
return 0;
}
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
Mi[i][j] *= Q[i][j];
}
}
if(T == 1){
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
if(j) cout << ' ';
cout << Mi[i][j];
}
cout << endl;
}
return 0;
}
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
M[i][j] = Mi[i][j];
}
}
const ld PI = acosl(-1.0L);
alpha[0] = sqrtl(0.5L);
for(int u = 1;u < 8;u++){
alpha[u] = 1.0L;
}
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
for(int u = 0;u < 8;u++){
for(int v = 0;v < 8;v++){
Mp[i][j] += 0.25 * alpha[u] * alpha[v] * Mi[u][v] * cosl(PI / 8 * (i + 0.5) * u) * cosl(PI / 8 * (j + 0.5) * v);
}
}
}
}
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
ld x = Mp[i][j] + 128.0L;
ll val = llroundl(x);
if(val < 0) val = 0;
if(val > 255) val = 255;
res[i][j] = (int)val;
}
}
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
if(j) cout << ' ';
cout << res[i][j];
}
cout << endl;
}
return 0;
}