一、动态规划思想
把待求解问题分解成若干个子问题,先求解子问题,
然后由这些子问题的解得到原问题的解,但动态规划求解过的子问题的结果会
被保留下来,不像递归那样每个子问题的求解都要从头开始返回求解。动态规
划求解问题的关键在于获得各个阶段子问题的递推关系式:
- 分析原问题的最优解性质,刻画其结构特征
- 递归定义最优值
- 自底向上(由后向前)的方式计算最优值
- 根据计算最优值时得到的信息,构造一个最优解。
1、动态规划的最优决策原理
活动过程划分为若干个阶段,每一阶段的决策,依赖于前一阶段的状态,由决策所采取的动作,使状态发生转移,成为下一阶段的决策依据。
图6.1 动态规划的决策过程
最优性原理:无论过程的初始状态和初始决策是什么,其余决策都必须相对于初始决策所产生的状态,构成一个最优决策序列。
令最优状态为 ,由此倒推:
最优决策序列,
状态转移序列:
赖以决策的策略或目标,称为动态规划函数。
整个决策过程,可以递归地进行,或用循环迭代的方法进行。
动态规划函数可以递归地定义,也可以用递推公式来表达。
最优决策是在最后阶段形成的,然后向前倒推,直到初始阶段;
而决策的具体结果及所产生的状态转移,却是由初始阶段开始进行计算的,然后向后递归或迭代,直到最终结果。
二、多段图问题
若存在一个有向加权图 G,且 G 能分出起点和终点以及中间的 n 的阶段,求起
点到终点的最短(长)距离。
1、多段图动态规划算法思想
- 将图中的顶点划分 5 个阶段,k
- 每个阶段有几种供选择的点 s
- 当前状态应在前一个状态的基础上获得。决策需要满足规划方程
- 规划方程:f(k)表示状态 k 到终点状态的最短距离。
初始条件:f(k)=0,k=0;
f(k-1)=min{f(k)+W(k-1,k)}其中 W(k-1,k)表示状态 k-1 到状态 k 的距离
2、多段图动态规划算法 源码:
public class MinDistance {
static int N=13; //结点个数,从1开始
static int K=5; //阶段数量,从1
static int MAX=1000; //定义一个最大值,用于初始化
static int[][] c=new int[N][N]; //c[i][j]表示i到j的花费
static int[] cost=new int[N]; //cost[i]表示到结点i的最小花费
static int[] d=new int[N]; //d[i]表示由结点i指向的最小成本边的另一端的结点
static int[] p=new int[K]; //每一阶段最短路径
public static void main(String[] args) {
//------------------初始化数据------------------------
for (int i = 1; i < N; i++)
{
cost[i] = 0;
for (int j = 1; j < N; j++)
{
c[i][j] = MAX;
}
}
c[1][2] = 9;
c[1][3] = 7;
c[1][4] = 3;
c[1][5] = 2;
c[2][6] = 4;
c[2][7] = 2;
c[2][8] = 1;
c[3][6] = 2;
c[3][7] = 7;
c[4][8] = 11;
c[5][7] = 11;
c[5][8] = 8;
c[6][9] = 6;
c[6][10] = 5;
c[7][9] = 4;
c[7][10] = 3;
c[8][10] = 5;
c[8][11] = 6;
c[9][12] = 4;
c[10][12] = 2;
c[11][12] = 5;
fGraph();
int k = K;
int sum = 0;
int n = N - 1;
while (k != 1)//遍历每个阶段的最短路径成本
{
p[k-1]=n;
sum += cost[n];
n = d[n];
k--;
}
System.out.println("最短路径长度:"+sum);
System.out.print("最短路径:1");
for(int i=1;i<5;i++){
System.out.print("->"+p[i]);
}
}
public static void fGraph() //采用向前处理的方法
{
int min;
for (int j = N-1; j > 0; j--)
{
min = MAX;
for (int i = j; i > 0; i--)
{
if (c[i][j] != MAX && cost[j] + c[i][j] < min)
{
min = cost[i] + c[i][j];
d[j] = i;
}
}
cost[j] = min;//cost[j]保留到结点j的最短边的权值
}
}
}
3、算法分析
时间复杂度:O(n+m)
10~13行的初始化,花费 O(n) 时间。
14~23行局部决策,假定图的边数为 ,则花费时间为 O(n+m)。
24~28行形成最优决策序列,若多段图分为 k 段,花费 O(k) 时间。