一.分治策略
1.理论介绍:
2.基本步骤:
1分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
2解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
3合并:将各个子问题的解合并为原问题的解;
3.算法应用:
I. 最大子数组问题();
II.归并排序()、快速排序(Partition每次都划分得很均匀情况下为);
二.动态规划
1.理论介绍:
I.两个要素:最优子结构和子问题重叠;
(1)最优子结构性质:问题的最优解所包含的子问题的解也是最优的;
(2)子问题重叠性质:递归算法自顶向下对问题进行求解时,每次产生的子问题并不总
是新问题,有些会被重复计算多次,DP利用子问题的重叠性质,对每一个子问题
只计算一次,然后将其计算结果保存,从而获得较高的效率;
II.通常基于一个递推公式以及一个或者多个初始状态(状态和状态转移方程);
2.算法应用:
I.凑数问题:面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?
递推公式:,其中,表示 第j个硬币的面值;
II.求最长非降序子序列的长度LIS:
递推公式:,其中,求就把i前面的各个子序列中, 最后一个数不大于的序列长度加1,然后取出最大的长度即为,若i前面的各个子序列中最后一个数都大于,那么;
III.钢条切割问题:
递推公式:
IV.最长公共子序列LCS:
LCS的最优子结构:令和为两个序列,为X和Y的任意LCS.
1.如果,则且是和的一个LCS;
2.如果,那么意味着Z是和Y的一个LCS;
3.如果,那么意味着Z是X和的一个LCS;
三.贪心算法
1.理论介绍:
I.基本概念:
II.基本思路:
1.建立数学模型来描述问题;
2.把求解的问题分成若干个子问题;
3.对每一子问题求解,得到子问题的局部最优解;
4.把子问题的解局部最优解合成原来解问题的一个解;
III.适用问题:局部最优策略能产生全局最优解;
2.贪心算法和动态规划算法比较:
I.贪心算法作出的每步贪心决策都无法改变,由上一步的最优解推导下一步的最优解,而上一部之前的最优解则不作保留;
II.全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解;
III. 动态规划的关键是状态转移方程, 边界条件是可以直接得出的局部最优解;
四.所有结点对的最短路径问题
1.Floyd-Warshall算法
I.算法思想:
(1)从任意结点i到任意结点j的最短路径存在2种可能:
第一种:直接从i到j;
第二种:从i经过若干个结点k到j;
(2)设Dis(i,j)为结点i到j的最短路径距离,对每个结点k,判断Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立;若成立,证明从i到k再到j的路径比i直接到j的路径短,更新Dis(i,j),当遍历完所有结点k,Dis(i,j)中记录的便是i到j的最短路径的距离;
(3)Dis(i,j)计算过程中用到子问题的最优解,同时存在子问题重叠;
II递推公式:
III.算法伪代码:
FLOYD-WARSHALL(W)
1 n=W.rows
2 D(0)=W
3 for k=1 to n
4 let D(k)=(d(k)ij) be a new n*n matrix
5 for i=1 to n
6 for j=1 to n
7 d(k)ij=min(d(k-1)ij,d(k-1)ik+d(k-1)kj)
8 path[i][j]=k
9 return D(n)
(注:矩阵Path记录i,j两点之间最短路径所必须经过的点, 矩阵d(k)ij记录结点之间的最短距离,时间复杂度)
五.用于稀疏图的Johnson算法
1.算法思想:
(1)若图G =(V, E)中权值全非负,则对所有结点运行一次dijkstra算法找出所有结点对的最短路径;
(2)若有非负值但无负环路,则由原图转换得到一组新的非负权重值,再使用(1)中的方法计算,将负值权重转换为非负值使用的方法是:
1.在原图上新加一个结点s,并将w(s, v) == 0;
2.对s运行BellmanFord函数计算出s到其他点的最短路径,h[i] = ,即s到v的最短路径值,即每个结点赋予一个值,用于重新计算边的权重,重新计算出来的权重即为非负值;
2.算法伪代码:
JOHNSON(G,w)
1 compute G'
2 if BELIMAN-FORD(G',w,s)==false
return "contains a negative-weight cycle"
3 else
for each vertex v∈G'.v
h(v)= computed by the Bellman-Ford
for each edge(u,v)∈G'.E
let D=(duv)be a new n*n matrix
for each vertix u∈G.V
run Dijkstar(G,w',u) to computefor all v∈G.V
for each vertex v∈G.V
d(u,v)= +h(v)-h(u)
(注:使用菲波那挈堆实现Dijkstra,则时间复杂度为,二叉堆实现时间复杂度为)
六.最大流
1.概念和定理:
I.流网络和流:
(1)容量值c(u,v),源结点s,汇点t,流f
(2)容量限制,流量守恒
II.残存网络:残存容量cf(u,v),残存网络Gf=(V,Ef)
IV.切割:净流量f(S,T),切割(S,T)的容量
V.最大流最小切割定理:
设f为流网络G=(V,E)的一个流,该流网络的源结点为s,汇点为t,则下面条件等价:
(1)f是G的一个最大流
(2)残存网络Gf不包括任何增广路径
(3)|f|=c(S,T),其中(S,T)是流网络G的某个切割
2.Ford-Fulkerson方法:
I.算法思想:
根据最大流最小切割定理
II.伪代码:
Ford-FulKERSON(G,s,t)
1 for each edge(u,v)∈G.E
2 (u.v).f=0
3 while there exists a path p from s to t in the residual netword Gf
4 cf(p)=min{ cf(u,v):(u,v)is in p}
5 for each edge(u,v) in p
6 if(u,v) in p
7 (u,v).f=(u,v).f+ cf(p)
8 else
9 (v.u).f=(v.u).f- cf(p)
(注:算法1-2行将流f初始化为0,算法3-9行重复在残存网络Gf中寻找增广路径,
再根据残存容量cf(p)对路径p上的流f增加,时间复杂度取决于寻找增广路径)
3.Edmonds-Karp算法
I.算法思想:
在Ford-Fulkerson算法的中采用广度优先搜索来寻找增广路径,即从源节点s到汇点t的最短路径,权重为单位距离;
II.时间复杂度分析:O(VE2);
4.最大二分匹配
I.基本概念:
匹配,最大匹配
II.寻找最大二分匹配:
(1)多源点多汇点的最大流问题转换为单源点单汇点的最大流问题;
(2)二分图G中的一个最大匹配数M的基数等于其对应的流网络G’中最大流f值;