矩阵连乘问题
问题描述
给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。
详细说明:
完全加括号的矩阵连乘积
定义
递归定义如下
计算乘法次数
解决方案
穷举
时间复杂度分析:
动态规划
状态转移方程
其中参数的含义:
代码
1 | public class MatrixChain { |
备忘录
动归的优化,与纯动态规划区别在于,原来的动态规划的递归方向从底往上,比如上面是先计算出长度为i的矩阵,再利用得到的结果计算长度为i+1的矩阵
备忘录是利用递归从顶往下
代码
1 | public static int lookupChain(int i, int j) { |
最长公共子序列
结构
注:公共子序列不一定连续
举例:X:A, B, C, C, D, E
Y:A, B, E, F
最长公共子序列:A, B, E
状态转移方程
c[ i ][ j ]记录序列和的最长公共子序列的长度
其中, Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。故此时C[i][j]=0。
动归计算最长子序列长度
1 | b[i][j] = 1 //情况一:X尾和Y尾相等 |
代码
1 | public static void lcsLength(int m, int n, char[] x, char[] y, int[][] c, int[][] b) { |
根据上面得到的b矩阵构造最长公共子序列
1 | public static void lcs(int i, int j, char[] x, int[][] b) { |
最大子段和
定义
最大子段和要求是连续的
分治算法
时间复杂度分析(类似快排)
动归算法
状态转移方程:
定义数组b[ j ]表示含义为一定要取数组a[ j ]的情况下,能得到的最大子列和
b[ j ]=max{ b[ j-1 ]+a[ j ],a[ j ]},1≤j≤n
代码
1 | public static int maxSum(int n, int[] a) { |
凸多边形最优三角剖分
定义
- 用多边形顶点的逆时针序列表示凸多边形
- 若vi与vj是多边形上不相邻的2个顶点,则线段vivj称为多边形的一条弦。
- 多边形的三角剖分是将多边形分割成互不相交的三角形的弦的集合T。
- 给定凸多边形P,以及定义在由多边形的边和弦组成的三角形上的权函数w。要求确定该凸多边形的三角剖分,使得即该三角剖分中诸三角形上权之和最小。
状态转移方程
• 定义t[ i ][ j ]1为凸子多边形{vi-1,vi,…,vj}2的最优三角剖分所对应的权函数值,为方便起见,设退化的多边形{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]可递归地定义为:
和之前矩阵连乘定义比较:
凸多边形是矩阵连乘的拓展,拓展结果就是最后w函数可以是各种自定义
代码
0-1 背包
定义:
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
0-1背包问题是一个特殊的整数规划问题。
动态转移方程
代码
原始版本求最大价值
原始版本求产生最大价值的方法
流水作业调度
定义
n个作业{1,2,…,n}要在由2台机器M1和M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,然后在M2上加工。M1和M2加工作业i所需的时间分别为ai和bi。 流水作业调度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少
直观来看,最佳调度应该是使机器M1没有空闲时间,同时机器M2的空闲时间最少。通常情况下,机器M2上会出现两种情况:一种是机器空闲,另一种是作业积压。
假设所有作业的集合为N={1, 2, ..., n}。S⊆N是N的作业子集。在一般情况下,当机器M1开始处理S中的作业时,机器M2可能正在处理其他作业,需要等待时间t才能开始处理S中的作业。我们将在这种情况下完成S中作业所需的最短时间记为T(S, t)。流水作业调度问题的最优解为T(N, 0)。(t = 0表示机器M2积压时间为0)
Johnson不等式
如果作业i和j满足min{bi,aj}≥min{bj,ai},则称作业i和j满足Johnson不等式。
算法
流水作业调度问题的Johnson算法 (1)令
(2)将N1中作业依ai的递增排序(不严格);将N2中作业依bi的递减排序(不严格); (3)N1中作业接N2中作业构成满足Johnson法则的最优调度。
最优二叉搜索树
二叉搜索树定义
- 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
- 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
- 它的左、右子树也分别为二叉排序树。
如下图所示
搜索的期望耗费
所有节点(包括成功与不成功)的概率和是1
期望耗费
从深度角度(根节点深度为0)
举例:
也可以从比较次数角度,比如根节点比较1次就能确定
构建最优二叉搜索树
任务描述
给了一堆节点和每个节点被搜索到的概率,要求建立一棵二叉搜索树,这棵树的期望耗费要最小
问题分析
最优子结构
\(w_{i, j}\)表示包括i到j的节点组成的子树的可能性的和,从i到j的节点是实际存在的节点序号,但是还包括他们的子节点
\(p_{i, j}\)表示包括i到j的节点组成的子树的平均“路长”
\(w_{i, j}p_{i,j}\)的积表示的是包括i到j的节点组成的树的"贡献"
一棵树要想期望耗费最小,就是这棵树的左右子树贡献最小
状态转移方程
代码分析
1 | Void OBST (int* a, int* b, int n, int **m, int **s, int **w) |
上面最好要有个矩阵模拟过程
问题:数组a是什么?数组b又是什么?