第6讲 - - 动态规划专题讲座

发布时间 : 星期二 文章第6讲 - - 动态规划专题讲座更新完毕开始阅读

printf(\}

运行程序示例:

请输入序列x:hsbafdreghsbacdba 请输入序列y:acdbegshbdrabsa 最长公共子序列的长度为:9 最长公共子序列为:adeghbaba

6.3 最优路径搜索

本节应用动态规划探讨两类最优路径搜索问题,一类是点数值路径,即连接成路径的每一个点都带有一个数值;另一类是边数值路径,即连接成路径的每一条边都带有一个数值。

6.3.1 点数值三角形的最优路径搜索

点数值三角形是一个二维数阵:三角形由n行构成,第k行有k个点,每一个点都带有一个数值数。点数值三角形的数值可以随机产生,也可从键盘输入。

最优路径通常由路径所经各点的数值和来确定。 1. 案例提出

在一个n行的点数值三角形中,寻找从顶点开始每一步可沿左斜(L)或右斜(R)向下至底的一条路径,使该路径所经过的点的数值和最小。

图6.1 7行点数值三角形 例如,n=7时给出的点数值三角形如图6.1所示,如何寻找从项到底的数值和最小路径?该最优路径的数值和为多少?

2.动态规划算法设计

设点数值三角形的数值存储在二维数组a(n,n)。 (1)建立递推关系

设数组b(i,j)为点(i,j)到底的最小数值和,字符数组stm(i,j)指明点(i,j)向左或向右的路标。b(i,j)与stm(i,j)(i=n?1,?,2,1)的值由b数组的第i+1行的第j个元素与第j+1个元素值的大小比较决定,即有递推关系:

b(i,j)=a(i,j)+b(i+1,j+1); stm(i,j)=“R” (b(i+1,j+1)

其中i=n?1,?,2,1

边界条件:b(n,j)=a(n,j), j=1,2,?,n。

所求的最小路径数值和即问题的最优值为b(1,1)。 (2)逆推计算最优值

for(j=1;j<=n;j++) b[n][j]=a[n][j];

for(i=n?1;i>=1;i??) // 逆推得b[i][j] for(j=1;j<=i;j++)

if (b[i+1][j+1]

{b[i][j]=a[i][j]+b[i+1][j+1];stm[i][j]='R';} else

{b[i][j]=a[i][j]+b[i+1][j];stm[i][j]='L';} Printf(\(3)构造最优解

为了确定与并输出最小路径,利用stm数组从上而下查找: 先打印a(1,1),若stm(1,1)=“R”,则下一个打印a(2,2),否则打印a(2,1)。 一般地,在输出i循环(i=2,3,?,n)中:

若stm(i?1,j)=“R”则打印“?R?”;a(i,j+1);同时赋值j=j+1。 若stm(i?1,j)=“L”则打印“?L?”;a(i,j); 依此打印出最小路径,即所求的最优解. (4)算法的复杂度分析

22

以上动态规划算法的时间复杂度为O(n),空间复杂度也为O(n)。 2.最小路径寻求与测试程序设计 // 点数值三角形的最小路径 #include #include #include void main() { int n,i,j,t;

int a[50][50],b[50][50]; char stm[50][50]; printf(\请输入数字三角形的行数n:\ scanf(\

t=time(0)00; srand(t); //随机数发生器初始化 for(i=1;i

{for(j=1;j<=36-2*i;j++) printf(\ for(j=1;j<=i;j++)

{a[i][j]=rand()/1000+1;

printf(\// 产生并打印n行数字三角形 }

printf(\

}

printf(\请在以上点数值三角形中从顶开始每步可左斜或右斜至底\ printf(\寻找一条数字和最小的路径.\\n \ for(j=1;j<=n;j++) b[n][j]=a[n][j];

for(i=n-1;i>=1;i--) // 逆推得b[i][j] for(j=1;j<=i;j++)

if (b[i+1][j+1]

{b[i][j]=a[i][j]+b[i+1][j+1];stm[i][j]='R';} else {b[i][j]=a[i][j]+b[i+1][j];stm[i][j]='L';}

printf(\最小路径和为:%d\\n\// 输出最小数字和 printf(\最小路径为:%d\// 输出和最小的路径 for(i=2;i<=n;i++)

if(stm[i-1][j]=='R')

{ printf(\ else

printf(\ printf(\}

运行程序,对于数据如图所示的点数值三角形,输出如下: 最小路径和为:74

最小路径为:22-R-19-R-10-L-12-R-6-R-2-R-3

6.3.2 边数值矩形的最优路径搜索

边数值矩形也是一个二维数阵:矩形由n行m列构成,每一行有m?1条横边,每一列有n?1条竖边,每一条边都带有一个数值。最优路径通常由路径所经各边的数值和来确定。

1. 案例提出

已知n行m列的边数值矩阵,每一个点可向右或向下两个去向,试求左上角顶点到右下角顶点的所经边数值和最大的路径。

例如,给出一个4行5列的边数值矩形如图6.2所示,如何寻找从矩阵的左上角顶点到右下角顶点的数值和最大路径?该最优路径的数值和为多少?

图6.2 一个4行5列的边数值矩形

2.动态规划算法设计

设矩阵的行数n,列数m,每点为(i, j),i=1,2,?,n;j=1,2,?,m。显然,该边数值矩

阵每行有m?1条横向数值边,每列有n?1条纵向数值边。

从点(i,j)水平向右的边长记为r(i,j)(j

设a(i,j)为点(i,j)到右下角顶点的最大路程。st(i,j)为点(i,j)路标数组,其值取为{‘d’,’r’}。

a(i,j)的值由a(i+1,j)+d(i,j)与a(i,j+1)+r(i,j)比较,取其较大者得到,即有递推关系:

a(i,j)=max(a(i+1,j)+d(i,j),a(i,j+1)+r(i,j)) st(i,j)={‘d’,‘r’}

其中i=1,2,?,n?1;j=1,2,?,m?1。

注意到右边纵列与下边横行只有惟一出口,因而有边界条件:

a(i,m)=a(i+1,m)+d(i,m); i=n?1,n?2,?,1 a(n,j)=a(n,j+1)+r(n,j); j=m?1,m?2,?,1 (2)逆推计算最优值 for(i=n?1;i>=1;i??)

{a[i][m]=a[i+1][m]+d[i][m];st[i][m]='d';} // 右边纵列初始化 for(j=m?1;j>=1;j??)

{a[n][j]=a[n][j+1]+r[n][j];st[n][j]='r';} // 下边横行初始化 for(i=n?1;i>=1;i??) // 逆推求解a(i,j) for(j=m?1;j>=1;j??)

if(a[i+1][j]+d[i][j]>a[i][j+1]+r[i][j]) {a[i][j]=a[i+1][j]+d[i][j];st[i][j]='d';} else

{a[i][j]=a[i][j+1]+r[i][j];st[i][j]='r';}

所求左上角顶点到右下角顶点的最大路程即最优值为a(1,1)。 (3)构造最优解

利用路标数组输出最优解,从点(1,1)即i=1,j=1开始判断:

if(st[i][j]=='d')

{printf(\?%d?\else

{printf(\?%d?\必要时可打印出点座标。 (4)算法的复杂度分析

2

以上动态规划算法的时间复杂度为O(n)。 3.求边数值矩阵图的最大路径程序设计 // 求边数值矩阵图的最大路径 #include #include #include

联系合同范文客服:xxxxx#qq.com(#替换为@)