参考书籍:算法设计与分析——C++语言描述(第二版)
算法设计策略-动态规划法
资源分配问题
资源分配问题
将n个资源分配给r个项目,已知如果把j个资源分配各第i个项目,可以收益
这一问题可以用一个多段图来描述,多段图共分为
多段图中每个状态
从源点s到任意结点
关键路径问题
关键路径问题
关键路径问题是求解一个带权有向无环图中两个结点间的最长路径问题。关键路径问题是一个AOE网络问题。
AOE(activity on edge)网络是一个带权有向图
利用AOE网络可以进行工程的安排。例如,研究完成整个工程至少需要多少时间,为缩短工期应该加快哪些活动的速度,以及决定哪些活动是影响工程进度的关键等。由于整个工程只有一个开始状态和一个完成状态,故正常情况下(无回路),AOE网中只有一个入度为零的结点,称为源点,以及一个出度为零的结点,称为汇点。
关键路径法是进行工程安排的一种方法。完成工程所需的最短时间是AOE网中从开始结点到完成结点的最长路径的长度。这条路径称为关键路径,分析关键路径的目的在于找到关键活动。所谓关键活动就是指对整个工程的最短工期有影响的活动,即如果它不能如期完成就会影响整个工程的进度。
最短完成时间:是从源点到汇点的最长路径长度。
关键路径:从源点到汇点的最长路径。
关键活动:关键路径上的活动。对整个工程的最短完成时间有影响的活动,即如它不能按期完成就会影响整个工程的进度。
找关键活动的目的:
+ 重视关键活动;
对关键活动投入较多的人力和物力,确保工程按期完成。
缩短整个工期。
关键活动对缩短整个工期起着至关重要的作用;非关键活动对缩短整个工期不起作用。
最优子结构和重叠子问题
最优子结构和重叠子问题是动态规划法求解的基本要素。关键路径问题可以用动态规划算法求解,正因为它具有最优子结构和重叠子问题特性。
容易证明,对于关键路径问题的最优解具有最优子结构特征。关键路径问题的最优解是从源点s到汇点t的最长路径,设为
求关键路径的动态规划算法
- 事件i可能的最早发生时间
earliest(i) :是指从开始结点s到结点i的最长路径的长度。 - 事件i允许的最迟发生时间
latest(i) :是指在不影响工期的条件下,事件i允许的最晚发生时间,它等于earliest(n−1) 减去从结点i到结点n-1的最长路径的长度。 - 关键活动:若
latest(i)−earliest(i)=w(i,j) ,则边<i,j> 代表的活动是关键活动。对于关键活动组成的关键路径上的每个点i,都有latest(i)=earliest(i) 。
初始时,
式中,
所谓某个事件允许的最迟发生时间是在保证最短工期的前提下计算的。以下是计算事件允许的最迟发生时间的递推式:
计算从汇点
关键路径问题同样存在重叠子问题,关键路径算法将子问题的最优解的值保存在earliest数组中。
关键路径算法
求解关键路径的基本步骤:
1. 对有向图G进行拓扑排序,确认是否为有向无环图;
2. 按拓扑次序计算
3. 按逆拓扑次序计算
4. 对每一条边
每对结点间的最短路径
问题描述
设
每对结点间的最短路径问题是指求图中任意一对结点i和j之间的最短路径。
迪杰斯特拉算法可以求解单源最短路径问题,其时间复杂度为
对于带权有向图的最短路径问题可以允许有向图包含负边,但不允许有路径长度为负值的回路。
弗洛伊德(Floyd)算法是一种动态规划算法,它求带权有向图
动态规划法求解
最优子结构
设图
最优解的递推关系
设
则
一般有,
式中,
以上的讨论归结为以下递推式:
式中,
重叠子问题
从递推式可以看出,为了计算
弗洛伊德算法
弗洛伊德算法是一种动态规划算法,它采用自底向上的方式对计算每个结点间的最短路径。设有向图存储在邻接矩阵
弗洛伊德算法使用一个二维数组path来记录相应的最短路径,
//弗洛伊德算法
template<class T>
void MGraph<T>::Floyd(T**& d,int**& path)
{
int i,j,k;
d=new T*[n];
path=new int *[n];
for(i=0;i<n;i++){
d[i]=new T[n];
path[i]=new int[n];
//初始化
for(j=0;j<n;j++){
d[i][j]=a[i][j];
if(i!=j && w[i][j]<INFTY)
path[i][j]=i;
else
path[i][j]=-1;
}
}
//考察结点
for(k=0;k<n;k++){
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(d[i][k]+d[k][j]<d[i][j]){
d[i][j]=d[i][k]+d[k][j];
path[i][j]=path[k][j];
}
}
}
}
}
弗洛伊德算法的时间复杂度为
定理:弗洛伊德算法得到的d[i][j],