3.7 图像压缩(动态规划)

详细请看代码注释、代码

在这里插入代码片#include 
#include 
using namespace std;

int n, a[1024], s[1024], l[1024], b[1024];
//	s[i] 代表{p0, p1, ..., pi} 的最小压缩存储位数 
//	l[i] 代表第 i 段的像素点的个数  
//	b[i] 代表在第 i 段的像素点的最大灰度值

void Traceback(int n, int &m, int *s, int *l)
{
	if(n == 0) return ;
//	s[]重新赋值,存储分段位置
	Traceback(n - l[n], m, s, l);
//	最后一段的段长度和像素位数存于 l[n] 和 吧b[n]中 
	s[m++] = n - l[n];//n - l[n] 
}

void OUtput(int *s, int *l, int *b, int n)
{
	printf("%d\n", s[n]);//之后的s[]数组会被重新赋值 
	int m = 0;
	Traceback(n, m, s, l);
	s[m] = n;
	for(int i = 1; i <= m; ++i)
	{
		l[i] = l[s[i]];//段长度 
		b[i] = b[s[i]];//存储位数	
	} 
	for(int i = 1; i <= m; ++i)
	{
		printf("段长度 : %d  存储位数 : %d\n", l[i], b[i]);
	}
}
 
int Length(int i)
{
	int k = 1;
	i /= 2;  //二进制存储 
	while(i > 0)
	{
		++k;
		i /= 2;
	}
	return k;
}

void Compress(int n, int *a, int *s, int *l, int *b)
{
	int i, j, Lmax = 256, header = 11;
	s[0] = 0;
//	递推关系式为: s[i] = min {s[i - k] + k * bmax(i - k + 1, i) + 1}
//                      1 <= k <= min{i, 255}
//                bmax(i, j) = log(max(pk) + 1) i <= k <= j (八位)向下取整
	  
	for(i = 1; i <= n; ++i)
	{
		b[i] = Length(a[i]); //计算b[i]所需要的存储位数 
		int bmax = b[i];     //后期更新bmax 
		s[i] = s[i - 1] + bmax;
		l[i] = 1;
		for(j = 2; j <= i && j <= Lmax; ++j)
		{
			if(bmax < b[i - j + 1])// i >= j, b[i]在不断更新, 后 -> 前 
			{
				bmax = b[i - j + 1];
			}
			if(s[i] > s[i - j] + j * bmax) 
			{
				s[i] = s[i - j] + j * bmax;
				l[i] = j;
			}	
		}
		s[i] += header; 
	}
}

int main()
{
	int i;
	scanf("%d", &n);
	for(i = 1; i <= n; ++i)
	{
		scanf("%d", &a[i]);
	}
//	从 n 开始 
	Compress(n, a, s, l, b);
	OUtput(s, l, b, n); 
	return 0;
}

你可能感兴趣的:(动态规划)