CCF刷题计划——JPEG 解码(状态方向辅助Z型填充)

JPEG 解码

计算机软件能力认证考试系统

这道题唯一的难点其实是处理数据Z型填入。本题可以学到:dir表示方向填充。相当于使用dir为状态机表示当前状态,根据当前状态进行移动。我看到有题解,可以直接枚举存储状态,也是一个不错的选择,就是输入的时候有点手痛。

这种问题(z型插入)也不是第一次见了,可以专门记一记,出现类似的也可以考虑使用dir状态表示。

bool dir=false;			//表示插入方向,一开始是向左下填充 
	int x=0,y=0;
	for(int i=0;i<n;i++)	//插入所有数据
	{
		m[x][y]=data[i];
		//四种情况:上右边界、右上移动、左下边界、左下移动(注意!顺序不能换。因为我们筛选是一步一步的) 
		if(!dir && (!x||y==7))	//之前是右上走的,判断是否到边界 当为上、右边界的时候,向左下移动
		{
			dir=true;
			y==7?x++:y++;	//当为上边界的时候,就x水平移动;为右边界的话,y竖直向下走 
		 }
		else if(!dir)	x--,y++;	//dir==false-->右上走
		else if (!y || x == 7) dir = false, x == 7 ? y++ : x++;	//同理,遇见左、下边界  
		else	x++,y--;
	}

AC:

#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
#define pi 3.1415926535

int n,T;
int lm[8][8]={0};	//量化矩阵 
int m[8][8]={0};	//经数据填充的矩阵 
int data[66]={0};

void Fill()	
{
//构造矩阵M的时候设置一个变量dir 表示方向,dir=true 时从左下往右上填充,dir=false 时从右上往左下填充。
//注意判断边界是两个维度都要考虑是否到达边界。
	bool dir=false;			//表示插入方向,一开始是向左下填充 
	int x=0,y=0;
	for(int i=0;i<n;i++)	//插入所有数据
	{
		m[x][y]=data[i];
		//四种情况:上右边界、右上移动、左下边界、左下移动(注意!顺序不能换。因为我们筛选是一步一步的) 
		if(!dir && (!x||y==7))	//之前是右上走的,判断是否到边界 当为上、右边界的时候,向左下移动
		{
			dir=true;
			y==7?x++:y++;	//当为上边界的时候,就x水平移动;为右边界的话,y竖直向下走 
		 }
		else if(!dir)	x--,y++;	//dir==false-->右上走
		else if (!y || x == 7) dir = false, x == 7 ? y++ : x++;	//同理,遇见左、下边界  
		else	x++,y--;
	}
}

void pirntMatrix()
{
	for(int i=0;i<8;i++)
		{
			for(int j=0;j<8;j++)
				cout<<m[i][j]<<" ";
			cout<<endl;
		}
}

void MulMatrix()
{
	for(int i=0;i<8;i++)
	for(int j=0;j<8;j++)
		m[i][j]*=lm[i][j];
}

void changeMatrix()
{
	double temp[8][8]={0};
	vector<double> a(8,1);
	a[0]=sqrt(0.5);
	
	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++)
					temp[i][j]+=0.25*a[u]*a[v]*m[u][v]*cos(pi/8*(i+0.5)*u)*cos(pi/8*(j+0.5)*v);

	for(int i=0;i<8;i++)
	for(int j=0;j<8;j++)
	{
		temp[i][j]+=128;
		temp[i][j]=temp[i][j]>255?255:temp[i][j];
		temp[i][j]=temp[i][j]<0?0:temp[i][j];
		//四舍五入
		int t= temp[i][j]+0.5;
		temp[i][j]=t;
	}
	
	for(int i=0;i<8;i++)
	{
		for(int j=0;j<8;j++)
			cout<<temp[i][j]<<" ";
		cout<<endl;
	}
 } 

int main()
{
	for(int i=0;i<8;i++)
	for(int j=0;j<8;j++)
		cin>>lm[i][j];
		
	cin>>n>>T;
	for(int i=0;i<n;i++)
		cin>>data[i];
	if(T==0)
	{
		Fill();
		pirntMatrix();
	}
	else if(T==1)
	{
		Fill();	//先填充
		MulMatrix();	//相乘 结果放在m中(不是矩阵乘法,就是对应值相乘) 
		pirntMatrix();
	}
	else
	{
		Fill();	//先填充
		MulMatrix();
		changeMatrix();	//变换 
	}
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值