目测这个题也是最优子结构问题,首先就是查找到当前数组中最优的切割点,然后进行切割,进入下一轮循环。
递推公式如下:
s [ i ] = m i n 1 ≤ k ≤ m i n { i , 256 } { s [ i − k ] + k × b m a x ( i − k + 1 , i ) } + 11 s[i]=min_{1\le k \le min\{i,256\}} \{ s[i-k] + k\times b max(i-k+1, i) \}+11 s[i]=min1≤k≤min{i,256}{s[i−k]+k×bmax(i−k+1,i)}+11
其中:
b m a x ( i , j ) = ⌈ l o g ( m a x i ≤ k ≤ j ( p k ) + 1 ) ⌉ b max(i,j)=\lceil log(max_{i\le k \le j} (p_k) +1 ) \rceil bmax(i,j)=⌈log(maxi≤k≤j(pk)+1)⌉
import java.util.Arrays;
/**
* @author:
* @description: 图像压缩的动态规划算法
* @date: Created in 2020/4/16 0:05
* @ersion: 1.0
*/
public class Work8 {
public Work8(){
int[] img = { 1, 10, 12, 255, 255, 1, 2, 1, 1, 2, 2, 1, 1 };
System.out.println( compImg(img) );
}
/**
* 将输入的数组进行切割
*
* @param image 一个一维数组
* @return 返回拆分后的数组的长度
* */
public int compImg( int[] image ){
//长度为零时返回结果,0
if ( image.length < 1 ){
return 0;
//长度为一时,返回这个数的长度加11
}else if ( image.length == 1 ){
System.out.println( image[0] );
return 11+Integer.toString( image[0], 2 ).length();
}
//用于存储image数组中每个空隙左右两侧的数的最长长度,len[0]存储左侧len[1]存储右侧
int[][] len = new int[image.length-1][2];
//首先将首尾的特殊情况进行处理
len[0][0] = Integer.toString( image[0], 2 ).length();
len[len.length-1][1] = Integer.toString( image[image.length-1], 2 ).length();
//暂存当前未分割情况下的数组的最长值,也是当前未分割情况下,数组每个单元需要的存储空间
int maxlen = Math.max( len[0][0], len[len.length-1][1] );
//对len数组进行赋值,并得到maxlen的值
//每次循环,只需要对当前值和前一个值进行比较,取最大值即可
//左侧最大值,从左向右遍历得到,右侧最大值由右至左遍历得到
for ( int i = 1, j = len.length-2; i < len.length; i++, j-- ){
int tmp = Integer.toString( image[i], 2 ).length();
len[i][0] = Math.max(len[i-1][0], tmp );
maxlen = Math.max( maxlen, tmp );
tmp = Integer.toString( image[j+1], 2 ).length();
len[j][1] = Math.max(len[j+1][1], tmp );
maxlen = Math.max( maxlen, tmp );
}
//数组最小所占空间
int sum = 11 + maxlen*(len.length+1);
//存储分割的位置,如果可以进行分割的话
int index = -1;
//遍历数组,得到最适合的切割位置
for ( int i = 0; i < len.length; i++ ){
int tmp = len[i][0]*(i+1) + len[i][1]*(len.length-i-1) + 22;
if ( tmp < sum ){
index = i;
sum = tmp;
}
}
//根据index的值,判断是否可以进行分割
//如果不行就输出结果,如果可以分隔就将数组进行切割,进入下一次循环
if ( index == -1 ){
for ( int i : image ){ System.out.print( i + "\t "); }
System.out.println( "sum:" + sum );
return sum;
}else {
return compImg(Arrays.copyOfRange( image, 0, index+1)) + compImg(Arrays.copyOfRange( image, index+1, image.length));
}
}
public static void main(String[] args) {
Work8 work8 = new Work8();
}
}