图像的变位压缩存储格式将所给的像素点序列{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[i−1]+k+header,dp[i−t]+t∗maxlen(i−t,i))
因此只需递归至dp[n]即可。
#includeusing namespace std; #define MAX 256 int main(){ int n; scanf("%d", &n); int a[n],dp[n+1]; for(int i=0;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 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("%dn",dp[j]); // printf("n"); } } //测试数据: //6 10 12 15 255 1 2
主要的难点是理解题目和考虑循环中的临界值。



