【算法分析与设计】动态规划(下)

目录

  • 一、最长公共子序列
    • 1.1 最长公共子序列的结构
    • 1.2 子问题的递归结构
    • 1.3 计算最优值
    • 1.4 举例说明
    • 1.5 算法的改进
  • 二、最大子段和
    • 2.1 代码
    • 2.2 最大子段和问题的分治算法
    • 2.3 代码
    • 2.4 分治算法的时间复杂度
    • 2.5 最大子段和问题的动态规划算法
  • 三、凸多边形最优三角剖分
    • 3.1 三角剖分的结构及其相关问题
    • 3.2 最优子结构性质
    • 3.3 最优三角剖分的递归结构
  • 四、图像压缩
  • 五、电路布线
    • 5.1 代码
  • 六、流水作业调度
  • 七、投资问题
    • 7.1 实例
    • 7.2 子问题界定和计算顺序
    • 7.3 优化函数的递推方程
    • 7.5 k=1时实例的计算
    • 7.6 k=2时的实例计算
    • 7.7 备忘录和解
  • 八、0-1背包问题
    • 8.1 算法改进
    • 8.2 一个例子
    • 8.3 算法改进
    • 8.4 一个例子
    • 8.5 算法复杂度分析
  • 九、最优二叉搜索树
    • 9.1 二叉搜索树
    • 9.2 二叉搜索树的期望耗费
    • 9.3 二叉搜索树的期望耗费示例
    • 9.4 最优二叉搜索树
  • 十、小结


一、最长公共子序列

  若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的 子序列 是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。
  给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列
  给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的 最长公共子序列


1.1 最长公共子序列的结构

  设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk} ,则
  (1)若xm=yn则zk=xm=yn,且zk-1是xm-1和yn-1的最长公共子序列
  (2)若xm≠yn且zk≠xm,则 Z是xm-1和Y的最长公共子序列
  (3)若xm≠yn且zk≠yn,则 Z是X和yn-1的最长公共子序列

  由此可见,2个序列的最长公共子序列包含了这2个序列的前缀的最长公共子序列。因此,最长公共子序列问题具有最优子结构性质


1.2 子问题的递归结构

  由最长公共子序列问题的最优子结构性质建立子问题最优值的递归关系。用c[i][j]记录序列和的最长公共子序列的长度。其中, Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。故此时C[i][j]=0。其它情况下,由最优子结构性质可建立递归关系如下
在这里插入图片描述


1.3 计算最优值

  由于在所考虑的子问题空间中,总共有θ(mn)个不同的子问题,因此,用动态规划算法自底向上地计算最优值能提高算法的效率

void LCSLength(int m,int n,char *x,char *y,int **c,int **b)
{  int i,j;for (i = 1; i <= m; i++) c[i][0] = 0;for (i = 1; i <= n; i++) c[0][i] = 0;for (i = 1; i <= m; i++)for (j = 1; j <= n; j++) {if (x[i]==y[j]) { c[i][j]=c[i-1][j-1]+1; b[i][j]=1;}else if (c[i-1][j]>=c[i][j-1]) {c[i][j]=c[i-1][j]; b[i][j]=2;}else { c[i][j]=c[i][j-1]; b[i][j]=3; }}
}
//构造最长公共子序列
void LCS(int i,int j,char *x,int **b)
{if (i ==0 || j==0) return;if (b[i][j]== 1){ LCS(i-1,j-1,x,b); cout<<x[i]; }else if (b[i][j]== 2) LCS(i-1,j,x,b);else LCS(i,j-1,x,b);
}

1.4 举例说明

在这里插入图片描述


1.5 算法的改进

  在算法lcsLength和lcs中,可进一步将数组b省去。事实上,数组元素c[i][j]的值仅由c[i-1][j-1],c[i-1][j]和c[i][j-1]这3个数组元素的值所确定。对于给定的数组元素c[i][j],可以不借助于数组b而仅借助于c本身在时间内确定c[i][j]的值是由c[i-1][j-1],c[i-1][j]和c[i][j-1]中哪一个值所确定的。
   如果只需要计算最长公共子序列的长度,则算法的空间需求可大大减少
  事实上,在计算c[i][j]时,只用到数组c的第i行和第i-1行。因此,用2行的数组空间就可以计算出最长公共子序列的长度。进一步的分析还可将空间需求减至O(min(m,n))


二、最大子段和

  子段:数列中的连续若干子数列的集合
  问题:给定由n个整数(可能为负整数)组成的序列a1,a2,…an,求该序列的子段和的最大值
  当所有整数均为负整数时,定义其最大子段和为零
  例如,当(a1,a2,a3,a4,a5,a6)=(-2,11,-4,13,-5,-2)时,最大子段和为20。


2.1 代码

int MaxSum(int n,int *a){int besti,bestj;int i,j,k,thissum;int sum=0;for(i=1;i<=n;i++){for(j=i;j<=n;j++){thissum=0;for(k=i;k<=j;k++)thissum+=a[k];if (thissum>sum){sum=thissum;besti=i;bestj=j;}}}
return sum;
} 

2.2 最大子段和问题的分治算法

  将所给的序列a[1:n],分成长度相等的两端a[1:n/2]和 a[n/2+1:n],分别求出这两端的最大子段和,则 a[1:n]的最大子段和有三种情况
  a[1:n]的最大子段和与a[1:n/2]的最大子段和相同;
  a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同;
  a[1:n]的最大子段和跨越a[1:n/2]和a[n/2+1:n]两个区域。
  对于3,容易看出,a[n/2]与a[n/2+1]必在最优子序列中
  在a[1:n/2]中计算出s1为含有a[n/2]的最大子段和。
  在a[n/2+1:n]中计算出s2为含有a[n/2+1]的最大子段和。
  则s1+s2即为出现情形3时的最优值。

int MaxSubSum(int *a,int left,int right){int sum=0;int center;int leftsum,rightsum;int i,s1,s2,lefts,rights;if(left==right)sum=a[left]>0?a[left]:0;else{center=(left+right)/2;leftsum=MaxSubSum(a,left,center);rightsum=MaxSubSum(a,center+1,right);s1=0;lefts=0;for(i=center;i>=left;i--){lefts+=a[i];if(lefts>s1)s1=lefts;}s2=0;rights=0;for(i=center+1;i<=right;i++){rights+=a[i];if(rights>s2)s2=rights;}

2.3 代码

sum=s1+s2;if(sum<leftsum)sum=leftsum;if(sum<rightsum)sum=rightsum;}return sum;
}

2.4 分治算法的时间复杂度

  该算法所需的计算时间T(n)满足典型的分治算法递归式
在这里插入图片描述
  解此递归方程可知,T(n)= O(nlogn)


2.5 最大子段和问题的动态规划算法

  若记b[j]为必须包含a[j]的左侧连续数据的最大子段和,则所求的最大子段和为max(1到n) b[j],再用变量sum存储当前b[j]的最大值即可。
  由于程序只用了一个for循环,所以此算法的时间复杂度为O(n)
  由b[j]的定义易知:
  当b[j-1]>0 时,b[j]= b[j-1]+a[j],否则b[j]= a[j]。由此可得b[j]的动态规划递归式b[j]= max{b[j-1]+a[j],a[j]},1<=j<=n。
  据此,可以设计出求最大字段和的动态规划算法

  代码如下:

int MaxSum(int n,int *a){int i,sum=0,b=0;for(i=1;i<=n;i++){if(b>0)b+=a[i];elseb=a[i];if(b>sum)sum=b;}return sum;
}

三、凸多边形最优三角剖分

  用多边形顶点的逆时针序列表示凸多边形,即P={v0,v1,…,vn-1}表示具有n条边的凸多边形
  若vi与vj是多边形上不相邻的2个顶点,则线段vivj称为多边形的一条弦。弦将多边形分割成2个多边形{vi,vi+1,…,vj}和{vj,vj+1,…vi}。
  多边形的三角剖分是将多边形分割成互不相交的三角形的弦的集合T
  给定凸多边形P,以及定义在由多边形的边和弦组成的三角形上的权函数w。要求确定该凸多边形的三角剖分,使得即该三角剖分中诸三角形上权之和为最小
在这里插入图片描述


3.1 三角剖分的结构及其相关问题

  一个表达式的完全加括号方式相应于一棵完全二叉树,称为表达式的语法树。例如,完全加括号的矩阵连乘积((A1(A2A3))(A4(A5A6)))所相应的语法树如图 (a)所示。
  凸多边形{v0,v1,…vn-1}的三角剖分也可以用语法树表示。例如,图 (b)中凸多边形的三角剖分可用图 (a)所示的语法树表示。
  矩阵连乘积中的每个矩阵Ai对应于凸(n+1)边形中的一条边vi-1vi。三角剖分中的一条弦vivj,i<j,对应于矩阵连乘积A[i+1:j]。
在这里插入图片描述


3.2 最优子结构性质

  凸多边形的最优三角剖分问题有最优子结构性质
  事实上,若凸(n+1)边形P={v0,v1,…,vn-1}的最优三角剖分T包含三角形v0vkvn,1≤k≤n-1,则T的权为3个部分权的和:三角形v0vkvn的权,子多边形{v0,v1,…,vk}和{vk,vk+1,…,vn}的权之和。
  可以断言,由T所确定的这2个子多边形的三角剖分也是最优的。因为若有{v0,v1,…,vk}或{vk,vk+1,…,vn}的更小权的三角剖分将导致T不是最优三角剖分的矛盾


3.3 最优三角剖分的递归结构

  定义t[i][j],1≤i<j≤n为凸子多边形{vi-1,vi,…,vj}的最优三角剖分所对应的权函数值,即其最优值。为方便起见,设退化的多边形{vi-1,vi}具有权值0。据此定义,要计算的凸(n+1)边形P的最优权值为t[1][n]。
  t[i][j]的值可以利用最优子结构性质递归地计算。当j-i≥1时,凸子多边形至少有3个顶点。由最优子结构性质,t[i][j]的值应为t[i][k]的值加上t[k+1][j]的值,再加上三角形vi-1vkvj的权值,其中i≤k≤j-1。由于在计算时还不知道k的确切位置,而k的所有可能位置只有j-i个,因此可以在这j-i个位置中选出使t[i][j]值达到最小的位置。由此,t[i][j]可递归地定义为:
在这里插入图片描述


四、图像压缩

  图象的变位压缩存储格式将所给的象素点序列{p1,p2,…,pn},0≤pi≤255分割成m个连续段S1,S2,…,Sm。第i个象素段Si中(1≤i≤m),有l[i]个象素,且该段中每个象素都只用b[i]位表示。
  设在这里插入图片描述
  则第i个象素段Si为在这里插入图片描述
  设在这里插入图片描述,则hib[i]8。因此需要用3位表示b[i],如果限制1l[i]255,则需要用8位表示l[i]。因此,第i个象素段所需的存储空间为l[i]*b[i]+11位。按此格式存储象素序列{p1,p2,…,pn},需要在这里插入图片描述位的存储空间。

  图象压缩问题要求确定象素序列{p1,p2,…,pn}的最优分段,使得依此分段所需的存储空间最少每个分段的长度不超过256位

  设l[i],b[i],是{p1,p2,…,pn}的最优分段。显而易见,l[1],b[1]是{p1,…,pl[1]}的最优分段,且l[i],b[i],是{pl[1]+1,…,pn}的最优分段。即图象压缩问题满足最优子结构性质。
设s[i],1≤i≤n,是象素序列{p1,…,pn}的最优分段所需的存储位数。由最优子结构性质易知:
在这里插入图片描述
  其中,在这里插入图片描述
  算法复杂度分析:
  由于算法compress中对k的循环次数不超这256,故对每一个确定的i,可在时间O(1)内完成的计算。因此 整个算法所需的计算时间为O(n)


五、电路布线

  在一块电路板的上、下2端分别有n个接线柱。根据电路设计,要求用导线(i,π(i))将上端接线柱与下端接线柱相连,如图所示。其中π(i)是{1,2,…,n}的一个排列。导线(i,π(i))称为该电路板上的第i条连线。对于任何1≤i<j≤n第i条连线和第j条连线相交的充分且必要的条件是π(i)>π(j)
  电路布线问题要确定将哪些连线安排在第一层上,使得该层上有尽可能多的连线。换句话说,该问题要求确定导线集Nets={(i,π(i)),1≤i≤n}的最大不相交子集
在这里插入图片描述
  记在这里插入图片描述
  N(i,j)的最大不相交子集为MNS(i,j)。Size(i,j)=|MNS(i,j)|。
  (1)当i=1时
在这里插入图片描述
  (2)当i>1时
  若j<π(i)。此时,
在这里插入图片描述
  故在这种情况下,N(i,j)=N(i-1,j),从而Size(i,j)=Size(i-1,j)。
2.2 j≥π(i),(i,π(i))∈MNS(i,j) 。 则对任意(t,π(t)) ∈MNS(i,j)有t<i且π(t)<π(i)。在这种情况下MNS(i,j)-{(i,π(i))}是N(i-1,π(i)-1)的最大不相交子集。
  若在这里插入图片描述
  则对任意(t,π(t)) ∈MNS(i,j)有t<i。从而
在这里插入图片描述
  因此,Size(i,j)≤Size(i-1,j)。
  另一方面,在这里插入图片描述
  故又有Size(i,j)≥Size(i-1,j),从而Size(i,j)=Size(i-1,j)。
在这里插入图片描述


5.1 代码

void MNS(int C[],int n){int i,j;for(j=0;j<C[1];j++){size[1][j]=0;}for(j=C[1];j<=n;j++){size[1][j]=1;}for(i=2;i<n;i++){for(j=0;j<C[i];j++){size[i][j]=size[i-1][j];}for(j=C[i];j<=n;j++){size[i][j]=size[i-1][j]>(size[i-1][C[i]-1]+1)?size[i-1][j]:(size[i-1][C[i]-1]+1);}}size[n][n]=size[n-1][n]>(size[n-1][C[n]-1]+1)?size[n-1][n]:(size[n-1][C[n]-1]+1);
}
void Traceback(int C[],int n,int NET[]){int i,j=n;int m=0;for(i=n;i>1;i--){if(size[i][j]!=size[i-1][j]){NET[m++]=i;j=C[i]-1;}if(j>=C[1])NET[m++]=1;}
} 

六、流水作业调度

  n个作业{1,2,…,n}要在由2台机器M1和M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,然后在M2上加工。M1和M2加工作业i所需的时间分别为ai和bi。
  流水作业调度问题要求确定这n个作业的最优加工顺序使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少

  分析:
  直观上,一个最优调度应使机器M1没有空闲时间,且机器M2的空闲时间最少。在一般情况下,机器M2上会有机器空闲作业积压2种情况。
  设全部作业的集合为N={1,2,…,n}。S⊆N是N的作业子集。在一般情况下,机器M1开始加工S中作业时,机器M2还在加工其它作业,要等时间t后才可利用。将这种情况下完成S中作业所需的最短时间记为T(S,t)。流水作业调度问题的最优值为T(N,0)

  设π是所给n个流水作业的一个最优调度,它所需的加工时间为 aπ(1)+T’。其中T’是在机器M2的等待时间为bπ(1)时,安排作业π(2),…,π(n)所需的时间。
  记S=N-{π(1)},则有T’=T(S,bπ(1))。

  证明:事实上,由T的定义知T’≤T(S,bπ(1))。若T’>T(S,bπ(1)),设π’是作业集S在机器M2的等待时间为bπ(1)情况下的一个最优调度。则π(1), π’(2),…, π’(n)是N的一个调度,且该调度所需的时间为aπ(1)+T(S,bπ(1))<aπ(1)+T’。这与π是N的最优调度矛盾。故T’≤T(S,bπ(1))。从而T’=T(S,bπ(1))。这就证明了流水作业调度问题具有最优子结构的性质

  由 流水作业调度问题的最优子结构性质 可知,
在这里插入图片描述
在这里插入图片描述


七、投资问题

  问题:m元钱,n项投资,fi(x):将x元投入第i个项目的效益。求使得总效益最大的投资方案
  建模:问题的解是向量<x1,x2,…xn>,xi是投给项目i的钱数,i=1,2,…,n
  目标函数max{f1(x1)+f2(x2)+…+fn(xn)}
  约束条件x1+x2+…+xn=m,xi∈N


7.1 实例

  5万元钱,4个项目,效益函数如下表所示
在这里插入图片描述


7.2 子问题界定和计算顺序

  子问题界定:由参数k和x界定
  k:考虑对项目1,2,…,k的投资
  x:投资总钱数不超过x

  原始输入:k=n,x=m
  子问题计算顺序:
  k=1,2,…,n
  对于给定的k,x=1,2,…,m


7.3 优化函数的递推方程

  Fk(x):x元钱投给前k个项目的最大效益
  多步判断若知道p元钱(p<=x)投给前k-1个项目的最大效益Fk-1§,确定x元钱投给前k个项目的方案
  递推方程和边界条件
  Fk(x)=max{fk(xk)+Fk-1(x-xk)} k>1
  F1(x)=f1(x)


7.5 k=1时实例的计算

  F1(1)=11。
  F1(2)=12。
  F1(3)=13。
  F1(4)=14。
  F1(5)=15。
在这里插入图片描述


7.6 k=2时的实例计算

  方案(其它,项目2):(0,1),(1,0)
  F2(1)=max{f2(1),f1(1)}=11
  方案:(0,2),(1,1),(2,0)
  F2(2)=max{f2(2),F1(1)+f2(1),F1(2)}=12
  方案:(0,3),(1,2),(2,1),(3,0)
  F2(3)=max{f2(3),F1(1)+f2(2), F1(2)+f2(1), F1(3)}=16
  类似的计算
  F2(4)=21, F2(5)=26


7.7 备忘录和解

在这里插入图片描述


八、0-1背包问题

  给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

  0-1背包问题是一个特殊的整数规划问题
在这里插入图片描述
在这里插入图片描述
  设所给0-1背包问题的子问题
在这里插入图片描述
在这里插入图片描述
  算法复杂度分析:
  从m(i,j)的递归式容易看出,算法需要O(nc)计算时间。当背包容量c很大时,算法需要的计算时间较多。例如,当c>2n时,算法需要Ω(n2n)计算时间
  最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。
在这里插入图片描述
在这里插入图片描述


8.1 算法改进

  由m(i,j)的递归式容易证明,在一般情况下,对每一个确定的i(1≤i≤n),函数m(i,j)是关于变量j的阶梯状单调不减函数。跳跃点是这一类函数的描述特征。在一般情况下,函数m(i,j)由其全部跳跃点唯一确定。如图所示。
在这里插入图片描述
  对每一个确定的i(1≤i≤n),用一个表p[i]存储函数m(i,j)的全部跳跃点。表p[i]可依计算m(i,j)的递归式递归地由表p[i+1]计算,初始时p[n+1]={(0,0)}。


8.2 一个例子

  n=3,c=6,w={4,3,2},v={5,2,1}。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


8.3 算法改进

  函数m(i,j)是由函数m(i+1,j)与函数m(i+1,j-wi)+vi作max运算得到的。因此,函数m(i,j)的全部跳跃点包含于函数m(i+1,j)的跳跃点集p[i+1]与函数m(i+1,j-wi)+vi的跳跃点集q[i+1]的并集中。易知,(s,t)q[i+1]当且仅当wisc且(s-wi,t-vi)p[i+1]。因此,容易由p[i+1]确定跳跃点集q[i+1]如下q[i+1]=p[i+1](wi,vi)={(j+wi,m(i,j)+vi)|(j,m(i,j))p[i+1]}
  另一方面,设(a,b)和(c,d)是p[i+1]q[i+1]中的2个跳跃点,则当ca且d<b时,(c,d)受控于(a,b),从而(c,d)不是p[i]中的跳跃点。除受控跳跃点外,p[i+1]q[i+1]中的其它跳跃点均为p[i]中的跳跃点。
  由此可见,在递归地由表p[i+1]计算表p[i]时,可先由p[i+1]计算出q[i+1],然后合并表p[i+1]和表q[i+1],并清除其中的受控跳跃点得到表p[i]。


8.4 一个例子

  n=5,c=10,w={2,2,6,5,4},v={6,3,5,4,6}。
  初始时p[6]={(0,0)},(w5,v5)=(4,6)。因此,q[6]=p[6](w5,v5)={(4,6)}。p[5]={(0,0),(4,6)}。q[5]=p[5](w4,v4)={(5,4),(9,10)}。
  从跳跃点集p[5]与q[5]的并集p[5]q[5]={(0,0),(4,6),(5,4),(9,10)}中看到跳跃点(5,4)受控于跳跃点(4,6)。将受控跳跃点(5,4)清除后,得到p[4]={(0,0),(4,6),(9,10)}。
  q[4]=p[4](6,5)={(6,5),(10,11)}
  p[3]={(0,0),(4,6),(9,10),(10,11)}
  q[3]=p[3](2,3)={(2,3),(6,9)}
  p[2]={(0,0),(2,3),(4,6),(6,9),(9,10),(10,11)}
  q[2]=p[2](2,6)={(2,6),(4,9),(6,12),(8,15)}
  p[1]={(0,0),(2,6),(4,9),(6,12),(8,15)}
  p[1]的最后的那个跳跃点(8,15)给出所求的最优值为m(1,c)=15。
在这里插入图片描述


8.5 算法复杂度分析

  上述算法的主要计算量在于计算跳跃点集pi。由于q[i+1]=p[i+1](wi,vi),故计算q[i+1]需要O(|p[i+1]|)计算时间。合并p[i+1]和q[i+1]并清除受控跳跃点也需要O(|p[i+1]|)计算时间。从跳跃点集p[i]的定义可以看出,p[i]中的跳跃点相应于xi,…,xn的0/1赋值。
  因此,p[i]中跳跃点个数不超过2n-i+1。由此可见,算法计算跳跃点集p[i]所花费的计算时间为在这里插入图片描述
  从而,改进后算法的计算时间复杂性为O(2n)。当所给物品的重量wi(1≤i≤n)是整数时,|p[i]|≤c+1,(1≤i≤n)。在这种情况下,改进后算法的计算时间复杂性为O(min{nc,2n})


九、最优二叉搜索树

9.1 二叉搜索树

  (1)若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值
  (2)若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值
  (3)它的左、右子树也分别为二叉排序树在随机的情况下,二叉查找树的平均查找长度和logn是等数量级的
在这里插入图片描述


9.2 二叉搜索树的期望耗费

  搜索成功与不成功的概率:
在这里插入图片描述
  二叉搜索树的期望耗费:
在这里插入图片描述
  有 个节点的二叉树的个数为:穷举搜索法的时间复杂度为指数级:
在这里插入图片描述
在这里插入图片描述


9.3 二叉搜索树的期望耗费示例

在这里插入图片描述
在这里插入图片描述


9.4 最优二叉搜索树

  最优二叉搜索树Tij的平均路长为pij,则所求的最优值为p1,n。由 最优二叉搜索树问题的最优子结构性质 可建立计算pij的递归式如下
在这里插入图片描述
  记wi,jpi,j为m(i,j),则m(1,n)=w1,np1,n=p1,n为所求的最优值。计算m(i,j)的递归式为
在这里插入图片描述
  注意到,
在这里插入图片描述
  可以得到O(n2)的算法。


十、小结

  动态规划算法和分治法的相同点是什么?
  动态规划算法和分治法的不同之处在哪里?
  用“表”记录所有已有子问题的答案!避免重复计算,从而得到多项式时间复杂度
  动态规划通常用来计算“最优”解,不适合计算“合并”解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91048.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring cloud Sentinel介绍和安装

Sentinel介绍和安装 &#x1f308;初识Sentinel&#x1f308;安装Sentinel&#x1f320;docker 安装&#x1f320;下载sentinel镜像&#x1f320;启动sentinel镜像 &#x1f320;windows 安装&#x1f320;下载&#x1f320;运行 &#x1f320;sentinel访问 &#x1f308;微服务…

Neo4j-双向关系

概述 这是GraphAware中关于双向关系的解释。 网址链接Modelling Data in Neo4j: Bidirectional Relationships | GraphAware 定向关系 Neo4j中的关系必须有一个语义化的类型和方向。 没有方向关系是模棱两可的&#xff0c;上面A队打败B队&#xff0c;如果没有方向&#xff0c…

【数据结构】什么是数据结构?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f38f;数据结构的定义 &#x1f38f;结语 &#x1f38f;数据结构的定义 数据结构(Data Structure)是计算机存储,组织数据的方式,指相互之间存在一种或多种特定关…

【自监督Re-ID】ICCV_2023_Oral | ISR论文阅读

Codehttps://github.com/dcp15/ISR_%20ICCV2023_Oral 面向泛化行人再识别的身份导向自监督表征学习&#xff0c;清华大学 目录 导读 摘要 相关工作 DG ReID 用于ReID的合成数据 无监督表征学习 Identity-Seeking Representation Learning 结果 消融实验 导读 新角度…

Linux常见指令2

Linux常见指令[2] 一.Linux常见指令1.man补充知识:nano 2.cp3.mv4.cat补充知识:echo输出重定向追加重定向回到catcat其他用法 5.less和more补充内容回到less 6.head和tail补充知识:命令行管道 一.Linux常见指令 前言:为了方便我们在Linux中写指令 介绍一下: 1.clear指令: 清屏…

【小沐学C++】C++ 基于Premake构建工程项目(Windows)

文章目录 1、简介2、下载和安装2.1 下载2.3 快速入门 3、使用3.1 支持的工程文件Project Files3.2 构建设置Build Settings3.3 链接Linking3.4 配置Configurations3.5 平台Platforms3.6 过滤Filters3.7 预设值Tokens 4、测试4.1 测试1&#xff1a;入门例子4.2 测试2&#xff1a…

Spring修炼之路(1)基础入门

一、简介 1.1Spring概述 Spring框架是一个轻量级的Java开发框架&#xff0c;它提供了一系列底层容器和基础设施&#xff0c;并可以和大量常用的开源框架无缝集成&#xff0c;可以说是开发Java EE应用程序的必备。Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器&…

【CTFHUB】SSRF绕过方法之靶场实践(二)

SSRF POST请求 提示信息&#xff1a; 这次是发一个HTTP POST请求.对了.ssrf是用php的curl实现的.并且会跟踪302跳转.加油吧骚年 首先测试了http的服务请求&#xff0c;出现对话框 输入数值后提示&#xff1a;只能接受来自127.0.0.1的请求 右键查看源码发现key值 通过file协…

一个简单的敏捷开发的例子

敏捷开发是一种以人为核心、迭代、循序渐进的软件开发方法。 敏捷开发以用户的需求进化为核心&#xff0c;采用迭代、循序渐进的方法进行软件开发。在敏捷开发中&#xff0c;软件项目在构建初期被切分成多个子项目&#xff0c;各个子项目的成果都经过测试&#xff0c;具备可视…

SpringMVC 学习(八)整合SSM

10. 整合 SSM (1) 新建数据库 CREATE DATABASE SSM;USE SSM;DROP TABLE IF EXISTS BOOKS;CREATE TABLE BOOKS (BOOK_ID INT(10) NOT NULL AUTO_INCREMENT COMMENT 书ID,BOOK_NAME VARCHAR(100) NOT NULL COMMENT 书名,BOOK_COUNTS INT(11) NOT NULL COMMENT 数量,DETAIL VARCH…

5.wifi开发【智能家居:上】,开发准备:智能开关灯,智能采集温湿,智能调彩灯

一。wifi智能家居项目开发 【开发准备1】&#xff1a;继电器控制开发 1.智能开关 器件准备&#xff1a;wifi&#xff08;esp8266&#xff0c;使用CP2102&#xff09;继电器 结果&#xff1a; 2.继电器工作原理 &#xff08;1&#xff09;继电器是一种自动电气开关 &#xff…

排序:外部排序算法分析

1.外存与内存之间的数据交换 1.外存&#xff08;磁盘&#xff09; 操作系统以“块”为单位对磁盘存储空间进行管理&#xff0c;如:每块大小1KB 各个磁盘块内存放着各种各样的数据。 2.内存 磁盘的读/写以“块”为单位数据读入内存后才能被修改修改完了还要写回磁盘。 2.外…

【数据结构】归并排序、基数排序算法的学习知识点总结

目录 1、归并排序 1.1 算法思想 1.2 代码实现 1.3 例题分析 2、基数排序 2.1 算法思想 2.2 代码实现 2.3 例题分析 1、归并排序 1.1 算法思想 归并排序是一种采用分治思想的经典排序算法&#xff0c;通过将待排序数组分成若干个子序列&#xff0c;将每个子序列排序&#xff…

C++中实现一些特殊的类|设计模式

1.设计一个类 不能被拷贝 拷贝只会发生在两个场景中&#xff1a;拷贝构造以及赋值运算符重载。想要让一个类禁止拷贝&#xff0c;只需要该类不能调用拷贝构造和赋值运算符重载 c98中 将拷贝构造与赋值运算符重载只声明不定义&#xff0c;不定义是因为该函数根本不会调用&#x…

【Java 进阶篇】MySQL多表查询之子查询详解

在数据库查询中&#xff0c;多表查询是一项非常常见且重要的任务。它允许我们从多个相关联的表中检索和组合数据&#xff0c;以满足各种复杂的查询需求。在多表查询中&#xff0c;子查询是一种强大的工具&#xff0c;用于在查询中嵌套另一个查询。本文将深入探讨MySQL中的子查询…

【Java】建筑工地智慧管理系统源码

智慧工地系统运用物联网信息技术&#xff0c;致力于推动建筑工程行业的建设发展&#xff0c;做到全自动、信息化&#xff0c;智能化的全方位智慧工地&#xff0c;实现工程施工可视化智能管理以提高工程管理信息化水平。 智慧工地平台拥有一整套完善的智慧工地解决方案&#xff…

源码编译安装zstd

目录 1 下载源码https://github.com/facebook/zstd 2 解压 3 在解压后的目录里输入make 4 sudo make install 安装完毕 5 输入whereis zstd 检查安装结果 1 下载源码https://github.com/facebook/zstd 2 解压 3 在解压后的目录里输入make 4 sudo make install 安装完毕…

图扑软件受邀亮相 IOTE 2023 国际物联网展

IOTE 2023 国际物联网展&#xff0c;作为全球物联网领域的盛会&#xff0c;于 9 月 20 日 - 22 日在中国深圳拉开帷幕。本届展会以“IoT构建数字经济底座”为主题&#xff0c;由深圳市物联网产业协会主办&#xff0c;打造当前物联网最新科技大秀。促进物联网与各行业深度融合&a…

安卓玩机-----给app加注册码 app加弹窗 云注入弹窗

在对接很多工作室业务中有些客户需要在他们自带的有些app中加注册码或者验证码的需求。其实操作起来也很简单。很多反编译软件有自带的注入功能。例如注入弹窗。这个是需要对应的注册码来启动应用。而且是随机id。重新安装app后需要重新注册才可以继续使用&#xff0c;原则上可…

mysql面试题5:索引、主键、唯一索引、联合索引的区别?什么情况下设置了索引但无法使用?并且举例说明

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说索引、主键、唯一索引、联合索引的区别? 索引、主键、唯一索引和联合索引是数据库中常用的索引类型,它们有以下区别: 索引:索引是一种数…