170 likes | 291 Vues
算法设计与分析 第三章 动态规划. 杨圣洪. 3.7 图像压缩. 将 像素点 灰度值序列 {p 1 ,p 2 ,…,p n } 分割成 m 个连续段 S 1 , S 2 ,… , S m 。 其中 0≤p i ≤255 。 0< 段内点数 <=255 Si 的点数记为 L[i] ,因 L[i] 255 , L[i] 的 2 进制之位数 8 Si 中各点的 p i 之 2 进制使用 相同位数 ( 即最大位数 bmax[i]) 。 p i 最大值 ≤ 255, 故 bmax[i] =ceil(log 2 (max( pi) )) 8 3 位 表示
E N D
算法设计与分析第三章 动态规划 杨圣洪
3.7 图像压缩 • 将像素点灰度值序列{p1,p2,…,pn}分割成m个连续段S1, S2 ,… , Sm。 其中0≤pi≤255。0<段内点数<=255 • Si的点数记为L[i],因L[i]255,L[i]的2进制之位数8 • Si中各点的pi之2进制使用相同位数(即最大位数bmax[i])。 • pi最大值≤255,故bmax[i]=ceil(log2(max(pi)))8 3位表示 • 如图像大块区域是浅色则像素值pi <32,bmax[i] 5 • 段i所占存贮空间L[i]*bmax[i]+点数(8位)+各点长度(3位) • 为解压需要,要保存点数L[i]、各点像素值的位数b[i],共有3+8=11位。故Si的存贮空间为: L[i]*b[i]+11 • 总长(L[1]*bmax[1]+11)+…+(L[m]*bmax[m]+11)= • (L[i]*bmax[i]+11m,i=1~m • 图象压缩问题:确定S1,S2,…,Sm,使得存储空间最少。 • 每段b[i]与L[i]如何组合。每段有表示点数与点长11位
最优子结构性质 • 设(L[1],bmax[1]),…, (L[m],b[m])是{p1,p2,…,pn}的最优分段。L[i]段i的长度,bmax[i]是段i的各像素值表示位数 • 如果整体最优能导出局部最优,否则矛盾(画示意图,局部换成最优后整体值会缩小,这与整体最优矛盾)。 • 为了找出最优分段,依次将每个点作为分段点(!!!),分别计算其区间长度与存贮空间,然后找出最佳分隔点。 • 设s[i]是以p[i] 分段点时,该段的存储位空间值则 • s[i]=min{s[i-k]+k*bmax(i-k+1, i)}+11,1kmin(i,255) • s[i-1]+1*bmax(i-1+1,i)+11, s[i-2]+2*bmax(i-2+1,i)+11, • bmax(j,i)=ceil(log2(max{p[k]}+1)) jki ,从点j到点i像素值最大者的位数,多算几个s[i]体会计算式 • i前255点内最少存贮空间,以i为结束点的段最多为255个点或最多包括之前的所有点。 • 算法复杂度分析:由于bmax(s,i)中对k的循环次数不超256,故对每一个确定的i,可在时间O(1)内完成的计算。因此整个算法所需的计算时间为O(n)。段长不超常量是技巧!
最优子结构性质 • 设(L[1],bmax[1]),…, (L[m],b[m])是{p1,p2,…,pn}的最优分段。L[i]段i的长度,bmax[i]是段i的各像素值表示位数 • 如果整体最优能导出局部最优,否则矛盾(画示意图,局部换成最优后整体值会缩小,这与整体最优矛盾)。 • 设s[i]是以p[i] 分段点时,该段的存储位空间值则 • s[i]=min{s[i-k]+k*bmax(i-k+1, i)}+11,1kmin(i,255) • 这个公式是对的,如下公式是错的! • s[i]=min{s[i-k]-11+k*bmax(i-k+1, i)}+11,1kmin(i,255) • S[0]=0 • S[1]=s[0]+1*bmax(1,1)+11=0+8+11=19 呆算8+11 • S[2]=s[1]+1*bmax(2,2)=27 ,S[0]+2*bmax(1,2)=0+16=16 • min(27,16)+11=27 呆算2*8+11= • S[3]=S[2]+1*bmax(3,3)=27+8=35,S[1]+2*bmax(2,3)=11+16=27 • S[0]+3*bmax(1,3)=0+24=24, min(35,27,24)+11=35 • 呆算:3*8+11=35 故这三个结果是对的
最优子结构性质 • 设(L[1],bmax[1]),…, (L[m],b[m])是{p1,p2,…,pn}的最优分段。L[i]段i的长度,bmax[i]是段i的各像素值表示位数 • 如果整体最优能导出局部最优,否则矛盾(画示意图,局部换成最优后整体值会缩小,这与整体最优矛盾)。 • 设s[i]是以p[i] 分段点时,该段的存储位空间值则 • s[i]=min{s[i-k]+k*bmax(i-k+1, i)}+11,1kmin(i,255) • S[0]=0 • S[1]=s[0]+1*bmax(1,1)+11=0+8+11=19 呆算8+11 • S[2]=s[1]+1*bmax(2,2)=27 ,S[0]+2*bmax(1,2)=0+16=16 • min(27,16)+11=27 呆算2*8+11= • S[3]=S[2]+1*bmax(3,3)=27+8=35,S[1]+2*bmax(2,3)=11+16=27 • S[0]+3*bmax(1,3)=0+24=24, min(35,27,24)+11=35 • S[4]=S[4-1]+1*bmax(4,4)=35+7=42,S[4-2]+2*bmax(3,4)=27+16=43 • S[4-3]+3*bmax(2,3)=19+24=43, S[4-4]+4*bmax(1,4)=32 • min(42,43,32)+11=43
s[i]=min{s[i-k]+k*bmax(i-k+1, i)}+11 bmax(i,j)=ceil(log2(max{p[k]}+1)) 1kmin(i,255) void compress(int n,int p[],int s[],int l[],int b[],int bmax[]){ //点数,像素值,结点i为终点段存贮空间,段长,本段内的素存贮位 int Lmax=255,header=11; //L[i]的值占8位,b[i]值占3位 s[0]=0;//没有一个点也要点数与最大位数,因此数组n+1位 for (int i=1;i<=n;i++){ b[i]=length(p(i)); //p(i)存贮位数 int bmax0=b[i]; //最大存贮位数初值为p(i)的位数 s[i]=s[i-1]+bmax0; //以i为终点的段长度初值k=1段时该段的长度 l[i]=1;bmax[i]=bmax0; //以i为终点的段内结点数初值为1 for (int k=2;k<=i && k<=Lmax;k++){ if (bmax0<b[i-k+1]) bmax0=b[i-k+1];//前面各点像素值位数已知 if (s[i]>s[i-k]+k*bmax){s[i]=s[i-k]+k*bmax0;l[i]=k;bmax[i]=bmax0;} } s[i]+=header;//添加固定的长度值 } } //L[i]保存着此点i前多少位共一段 int length(int i){ int k=1;i=(i>>1); //i=i/2; while (i>0){k++; i=(i>>1);} return k; }
s[i]=min{s[i-k]+k*bmax(i-k+1, i)}+11 kmax(i,j)=ceil(log2(max{p[k]}+1)) 1kmin(i,255) int Tb(int n,int sp[],int l[]){ int i=n; //最后一段结束位置 m=1; while (i>=1){ sp[m]=i;//段i的结束位置如500 m++; //逆向记录其位置 i=i-l[i]; } //前段结束位置如500-11 return m-1;}//返回段数 void Output(int l[],int b[],int n){ int sp[]=new int[n+1]; int m=Tb(n,sp,l); //计算各段结束点 for (int j=m;j>=1;j--){cout<< l[sp[j]]<<' '<<bmax[sp[j]]<<' '<<s[sp[j]]<<endl; }} l[n]最后一段长度,分隔点为n 倒数第1分隔点t2=n-l[n], 倒数第2分隔点t3=t2-l[t2] ……
递归计算最优值与构造最优解 • 递归计算最优值算法描述:P70-71 • 构造最优解算法描述:P71-72 • Compress:S(n)=O(n),T(n)=O(n)
3.8 电路布线 • 如下图所示,上方的点仅与下方一点相连 • 点i的对应点记为(i),其连线记为(i, (i)),称为第i条连线 • 制板时将线分布到若干绝缘层上,同层上的连线不许相交,为节约成本要使层次减少,每层不相交的连线增多 • 为此要求出某个电路不相交连线的最大值?,即求 • 导线集Nets={(i, (i)),1in}的最大不相交子集。 • 相交判断:任何1i<jn, 起点小终点大则相交 (i, (i))和(j, (j))相交 (i)>(j)。 各点的对象 ∏={8,7,4,2,5,1,9,3,10,6} 此图板书
最优子结构性质 • 记N(i,j)={(t, (t))|(t, (t))∈Nets,t≤i, (t)≤j}起点≤i,终点≤j. • N(1,1)= {起≤1,终≤1} ={}=N(1,2)…=N(1,7)=MNS(1,1) • N(1,8)= {起≤1,终≤8} ={(1,8)} • N(2,1)= {起≤2,终≤1} ={}=N(2,2)=N(2,3)…=N(2,6) • N(2,7)={起≤2,终≤7}={(2,7)} • N(2,8)={起≤2,终≤8}={(1,8),(2,7)} 相交 • N(3,9)={起≤3,终≤9}={(1,8),(2,7),(3,4)} 相交 • N(7,9)={起≤7,终≤9}={(1,8),(2,7),(3,4),(4,2),(5,5),(6,1),(7,8)} • 不相交={(3,4),(5,5),(7,8)},是最大吗? next • N(i,j)的最大不相交子集记为MNS(i,j),Size(i,j)=|MNS(i,j)|。 • (1)当i=1时, • (2)当i>1时, • 板N(i,j),MNS(i,j),Size(i,j),MNS(1,j),MNS(i>1,j)
N(i,j)={(t, (t))|(t, (t))∈Nets, t≤i, (t)≤j} 起点≤i,终点≤j. 最优子结构性质 (2)当i>1时, a) 终点j<(i)即i的端点在j的右边(i, (i))N(i,j) N(i,j)与前点i-1相同即 N(i,j)=N(i-1,j) MNS(i,j)=MNS(i-1,j)Size(i,j)=Size(i-1,j)。 b)终点j≥(i)(i终点(i)在j的左边)(i, (i))N(i,j) )分成以下二种情况: ① (i, (i))MNS(i,j)即新边在最大不相交子集中: 对于MNS(i,j)中不为(i,(i))的(t, (t)),其起点t<i,其端点(t)<(i) (i是N(i,j)各边起点最大值故t<i.假设(t)>(i)则(i, (i))与(t, (t))相交故矛盾) MNS(i,j)-{(i, (i))}=N(i-1, (i)-1)最大不相交子集MNS(i-1, (i)-1) Size(i,j)-1=Size(i-1,j-1) ( 假设MNS(i,j)-{(i, (i))}MNS(i-1, (i)-1) MNS(i,j)MNS(i-1, (i)-1){(i, (i))}, 而MNS(i-1, (i)-1){(i, (i))}是不相交子集,故MNS(i,j)不是最大,矛盾,故假设错。) ② (i, (i))MNS(i,j)即新边不在最大不相交子集中: (t, (t))MNS(i,j),其起点t<iMNS(i,j)N(i-1,j) MNS(i,j)MNS(i-1,j) Size(i,j)≤Size(i-1,j)。 又MNS(i-1,j)MNS(i,j)Size(i-1,j)Size(i,j)Size(i,j)=Size(i-1,j)。 电路布线问题整体最优Size(i,j)导出局部最优Size(i-1,j-1)
递归计算最优值 • 8 板书 ∏={8,7,4,2,5,1,9,3,10,6} 行i的终点 Size[1,1]=…=size[1,7]=0,size[1,8]=size[1,9]=1 size[2,1]=size[1,1],…,size[2,6]=size[1,6] size[2,7]=max(size[1,7],size[1,6]+1)=1,… size[3,1]=size[2,1],…size[3,3]=size[2,3] size[3,4]=max(size[2,4],size[2,3]+1)=1 size[4,1]=size[3,1], size[4,2]=max(size[3,2],size[3,1]+1)=1 size[5,1]=size[5,2]=size[5,3]=size[5,4]=上行值 size[5,5]=max(size[4,5],size[4,4]+1) ……
递归计算最优值 板书 void MNS(int C[], int n, int **size) //数组元素n+1 { //每个i的连接边(i)用数组C表示,如{8,7,4,2,5,1,9,3,10,6} ,size要返回! for (int j=1; j<C[1]; j++) size[1][j]=0;//i=1,j<(1)即结点1的终点 for (int j=C[1]; j<=n; j++) size[1][j]=1; //i=1,j>=(1)即结点1的终点 for (int i=2; i<=n; i++) //起点i从2起 { for (int j=1; j<C[i]; j++) size[i][j]=size[i-1][j]; //j< (i) for (int j=C[i]; j<=n; j++) //j>= (i) size[i][j]=max(size[i-1][j], size[i-1][C[i]-1]+1); }//起i终i范围为最后点n,j>= (n) size[n][n]==max(size[n-1][n], size[n-1][C[n]-1]+1); }
递归计算最优值 板书 ∏={8,7,4,2,5,1,9,3,10,6} 当size[i,j]<>size[i-1,j]才加边 i=2 j=C[3]-1=3 size[2][3]=size[1][3] i=3 j=4 size[3][4]<>size[2][4] net[3]=(3,C[3]) i=4 j=C[5]-1=4 size[4][4]=size[3][4] 不变 i=5 j=8 size[5][8]<>size[4][8] net[2]=(5,C[5]) i=6 j=C[7]-1=8 size[6][8]=size[5][8] j不变 i=7 j=9 size[7][9]<>size[6][9] net[1]=(7,C[7]) i=8j=C[9]-1=9 size[8][9]=size[7][9] j不变 i=9j=10 size[i][j]<>size[i-1][j] net[0]=(9,C[9]) i=n=10j=n=10 size[i][j]=size[i-1][j] j不变
跟踪路径 (i, (i))MNS(i,j)时 Size(i,j)=Size(i-1,j-1)+1 若size[i][j]=size[i-1][j-1]+1即size[i][j]!=size[i-1][j]就往MNS中加边(i, (i)). 保存该边起始号i,终止号(i)即C[i]. void Traceback(int C[],int **size, int n, int **Net, int &m){ int j=n; m=0; for (int i=n; i>1; i--) { if (size[i][j]!=size[i-1][j]){ Net[m][0]=i; Net[m][1]=C[i]; m++; j=C[i]-1; } } if (j>=C[1]) { Net[m][0]=1; Net[m][1]=C[i]; m++ } }
void MNS(int C[], int n, int **size) //数组元素n+1 { //每个i的连接边(i)用数组C表示,如{8,7,4,2,5,1,9,3,10,6} ,size要返回! for (int j=1; j<C[1]; j++) size[1][j]=0;//i=1,j<(1) for (int j=C[1]; j<=n; j++) size[1][j]=1; //i=1,j>=(1) for (int i=2; i<n; i++) //起点i从2起 { for (int j=1; j<C[i]; j++) size[i][j]=size[i-1][j]; for (int j=C[i]; j<=n; j++) //j>= (i) size[i][j]=max(size[i-1][j], size[i-1][C[i]-1]+1); }//起i终i范围为最后点n,j>= (n) size[n][n]==max(size[n-1][n], size[n-1][C[n]-1]+1);} 递归计算最优值 • 算法复杂性: • MNS算法:T(n)=O(n2),S(n)=(n2) • Traceback算法:T(n)=O(n) void Traceback(int C[],int **size, int n, int **Net, int &m){ int j=C[n]; m=0; for (int i=n; i>1; i--) { if (size[i][j]!=size[i-1][j]){ Net[m][0]=i; Net[m][1]=C[i]; m++; j=C[i]-1; } } if (j>=C[1]) { Net[m][0]=1; Net[m][1]=C[i]; m++ ;}}