图像压缩 动态规划C语言实现

问题描述

  图像的变位压缩存储格式将所给的像素点序列{p1,p2,…,pn},0≤pi≤255分割成m个连续段S1,S2,…,Sm。第i个像素段Si中(1≤i≤m),有l[i]个像素,且该段中每个像素都只用b[i]位表示。
   由于,b[i]<=8,需要用3位表示b[i];如果限制1<=l[i]<=256,则需要用8位表示l[i]。因此,第i个像素段所需的存储空间为l[i]*b[i]+11位。11是header,用来标记每段的特征的。

   按此格式存储像素序列{p1,p2,…,pn},需要 ∑ i = 1 m i = l [ i ] ∗ b [ i ] + 11 m \sum_{i=1}^mi=l[i]*b[i]+11m i=1mi=l[i]b[i]+11m 位。
   压缩则是就是把序列{p1,p1,……pn}进行设断点,将其分割成一段一段的。分段的过程就是要找出断点,让一段里面的像素的最大灰度值比较小,那么这一段像素(本来需要8位)就可以用较少的位(比如7位)来表示,从而减少存储空间。
在这里插入图片描述
   这里我们对上图分组:
   第一组4个数,最大是7所以用3位表示;
   第二组2个数,最大是245所以用8位表示;
   第三组6个数,最大是28所以用5位表示;
   这个时候,我们最后得到了最后的位数结果为:4*3+2*8+6*5+11*3=91。

思路

   第一想法:暴力枚举。细想发现实现比较困难,因为每段长度不定。
   这次的目的是寻找最小值,仔细想来还得是动态规划,从最优子结构推至全局最优解。那么还是原来的问题,最优子结构应该长什么样?
  假设第i个数长度是k,maxlen(i,j)用于寻找[i,j]中的最大长度,最优子结构应该为:
d p [ i ] = m a x ( d p [ i − 1 ] + k + h e a d e r , d p [ i − t ] + t ∗ m a x l e n ( i − t , i ) ) dp[i] = max(dp[i-1]+k+header, dp[i-t]+t*maxlen(i-t, i)) dp[i]=max(dp[i1]+k+header,dp[it]+tmaxlen(it,i))
   因此只需递归至dp[n]即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define MAX 256
int main(){
	int n;
	scanf("%d", &n);
	int a[n],dp[n+1];
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
		char result[10]; 
		itoa(a[i],result,2);	// 进制转换
		a[i] = strlen (result);
	}
	dp[0]=0;
	for(int i=0;i<n;i++){
		int maxlen = a[i];	// 假设这个最长 
		dp[i+1] = dp[i]+a[i];	// 假设是要直接接上去的 
		for(int len_picture=1; len_picture<=MAX && len_picture<=i+1; len_picture++){
			maxlen = max(maxlen, a[i-len_picture+1]);
			dp[i+1]=min(dp[i+1], dp[i+1-len_picture]+len_picture*maxlen);
		}
		dp[i+1]+=11;
//		for(int j=0;j<=i+1;j++)
//			printf("%d\n",dp[j]);
//		printf("\n"); 
	}
} 
//测试数据:
//6 10 12 15 255 1 2  

  主要的难点是理解题目和考虑循环中的临界值。

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

铖铖的花嫁

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值