一. 矩阵链乘
- 问题描述:给定n个矩阵:A1,A2,...,An,其中Ai与Ai+1是可乘的,i=1,2...,n-1。确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。
- 分析:用加括号来表达多个矩阵乘法的运算次序。
完全括号化:单一矩阵;两个完全括号化的矩阵乘积链的乘积,且已加外括号
-
1.存在最优子结构
2.递推关系:设计算A[i,j],1≤i≤j≤n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n]。当i=j时,A[i,j]=Ai,因此,m[i][i]=0,i=1,2,…,n;当i<j时,若A[i,j]的最优次序在Ak和Ak+1之间断开,i<=k<j,则:m[i][j]=m[i][k]+m[k+1][j]+pi-1*pk*pj。
3.计算最优值:依据其递归式以自底向上的方式进行计算。在计算过程中,保存以解决的子问题的答案,每个子问题只计算一次,而在后面用到时只需要查一下,避免了大量的重复计算。
4.重构最优解:将对应m[i][j]的断开位置k记为s[i][j],在计算出最优值m[i][j]后,可递归地由s[i][j]构造出相应的最优解。s[i][j]中的数表明,计算矩阵链A[i,j]的最佳方式应在矩阵Ak和Ak+1之间断开,即最优的加括号方式应为((A[i:k])(A[k+1:j]))。 -
求解最优值时三重循环,算法的时间复杂度为O(n3)。
二. 最长公共子序列(LCS)
- 问题描述:给出连个序列:X=<x1,x2,...xm>和Y=<y1,y1,...yn>,找出他们的最长公共子序列。
- 方法:暴力法(列出X所有可能子序列,检查是否也是Y的子序列,每次保留最长) O(n2m) 动态规划法 状态转移方程 c[i,j]=0 (i==0||j==0);c[i,j]=c[i-1,j-1]+1 (i,j>0 &&xi==yi); c[i,j]=max(c[i-1,j],c[i,j-1]} (i,j>0 && xi!=yi) 时间复杂度为O(nm)
- 题解:https://leetcode-cn.com/problems/longest-common-subsequence/solution/zui-chang-gong-gong-zi-xu-lie-by-leetcod-y7u0/
三. 0-1背包问题
- 问题描述:一个背包最大称重量为w,可放入背包的物品有n种,重量分别为w1,w2...wn,对应的价值分别为v1,v2...vn,求如何选择放入背包的物品,使得放入背包的物品价值最大。
- 暴力法:列出n种物品的所有可能的组合方式,检查是否可装入,并计算每种物品子集的价值,找到最大价值的物品子集 不可行 时间复杂度为O(2n)
- 动态规划:(二维动态化)用数组f[i][j]表示只看前i个物品,总重量是j的情况下,总价值最大是多少,那么最终结果为max(f[n][0~w])。状态转移方程为f[i][j]=f[i-1][j] 不选第i个物品;f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]) 选第i个物品 ;初始条件为f[0][0]=0。 时间复杂度为O(N*W)。空间复杂度为O(N*W)
- 动态规划改进:(一维数组)用一维数组f[],表示前i个物品重量为j时的最大价值,同时为第i次循环后f[j]中所表示的就是使用方法一中的f[i][j],此时的状态转移方程为 f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]),初始条件为f[0]=0;同时注意要解决因为数组状态更新问题所带来的问题而设置从后往前遍历。求解最优值的时间复杂度为O(nm),但是空间复杂度进行了优化,为O(m)
- 题解:https://www.acwing.com/video/214/