6动态规划算法的应用Word格式文档下载.docx
《6动态规划算法的应用Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《6动态规划算法的应用Word格式文档下载.docx(26页珍藏版)》请在冰豆网上搜索。
8结论12
致谢13
参考文献14
附录15
摘要
动态规划算法的有效性依赖于问题本身具有最优子结构性质和子问题重叠性质。
动态规划求最短路径,研究了任意点对的平面避障问题.用凸多边形表示障碍物,凸多边形的集合构成障碍环境.在此基础上,提出了一种新的路径规划思路:
对图结构进行扩展,用传统的Floyed算法进行一级规划;
对传统Floyed算法扩展后进行二级规划,很好地解决了任意点对的平面避障问题.利用矢量间夹角的关系来判断障碍环境中点对的连线是否交叉于多边形.经理论证明和算例验证,该算法方便简洁,容易实现,表明了算法的正确性.
用动态规划算法构造最优二叉搜索树的详细步骤,并用C++语言具体实现了该算法。
用一定的空间换取时间,提高了解决本问题的效率。
关键词:
凸多边形;
动态规划算法;
最优子结构;
子问题重叠;
最优二叉搜索树
1引言
1.1问题的提出
动态规划问世以来,在经济管理、生产调度、工程技术、和最优控制等方面得到了广泛的应用。
例如最短路线、库存管理、设备更新、排序、装载等问题,用动态规划方法比用其它方法求解更为方便。
1.2国内外研究的现状
现今动态规划主要用于求解以时间划分阶段的动态过程的优化问题,但是一些与时间无关的静态规划(如线性规划、非线性规划),只要人为地引进时间因素,把它视为多阶段决策过程,也可以用动态规划方法方便地求解。
1.3任务与分析
任务是实现多种问题的动态规划算法并分析、编程和总结,给出结论。
1、给出动态规划的基本思想;
2、给出最小代价子母树的动态规划算法和程序;
3、给出最短路径的动态规划算法和程序;
4、给出最优树的动态规划算法和程序。
动态规划算法分析;
1、动态规划算法的基本思想是①段化②自顶向下的分析③自底向上运算,此方法的正确性建立在最优性原理上。
2、设计动态规划算法的步骤
(1)找出最优解的性质,并刻划其结构特征。
(2)递归地定义最优值。
(3)以自底向上的方式计算出最优值。
(4)根据计算最优值时得到的信息,构造最优解。
3、针对算法实现,要求掌握算法的思想和原理,通过编程语言(VC、VB、Java等均可)实现算法。
4、具体算法和方案可参考任务书后相关参考文献。
2程序的主要功能
2.1求最短路径的功能
动态规划的正向思维方法的要点可归纳为一下三个步骤:
①构造状态网络;
②根据状态转移关系和状态转移方程建立最优值的递推计算式;
③按阶段的先后秩序计算每个状态的最优值。
2.2求最优树功能
步骤一:
寻找最优树结构。
一个最优二叉树的子树必定包含连续范围的关键字ki~kj,1<
=i<
=j<
=n,同时也必须含有连续的虚叶子节点di-1~dj。
如果一棵最优二叉查找树T有一棵含有关键字ki~kj的子树T'
,那么,T'
也是一棵最优查找树,这通过剪贴思想可以证明。
现在开始构造最优子结构:
在ki~kj中,选定一个r,i<
=r<
=j,使以kr为根,ki~k(r-1)和k(r+1)~kj为左右孩子的最优二叉树。
注意r=i或者r=j的情况,表示左子树或右子树只有虚叶子节点。
步骤二:
一个递归解。
定义e[i,j]为一棵包含关键字ki~kj的最优二叉树的期望代价。
当j=i-1时没有真实的关键在,只有虚叶子节点d(i-1)。
于是:
当j=i-1时,e[i,i-1]=q(i-1)。
当j>
=i时,需要选择合适的kr作为根节点,然后其余节点ki~K(r-1)和k(r+1)~kj构造左右孩子。
这时要考虑左右孩子这些节点成为一个节点的子树后,它的搜索代价的变化:
根据E[T]的计算,得知它们的期望代价增加了“子树中所有概率的总和”w。
w[i,j]=
pl//对每个l=i~j
+ql//对每个l=i-1~j
于是当j>
=i时,e[i,j]=pr+(e[i,r-1]+w[i,r-1])+(e[r+1,j]+w[r+1,j])=e[i,r-1]+e[r+1,j]+w[i,j];
步骤三:
计算最优二叉树的期望代价
e[i,j]=
q(i-1)
//如果j=i-1
min(e[i,r-1]+e[r+1,j]+w[i,j]),如果i<
=j,其中i<
=j
w[i,j]=
q(i-1)如果j=i-1
w[i,j]=w[i,j-1]+pj+qj如果i<
2.3求最小代价子母树功能
设有一排数,共n个,例如:
22,14,7,13,26,15,11。
任意两个相邻的数可以进行归并,归并的代价为
该两个数的和,经过不断的归并,最后归为一个堆,而全部归并代价的和称为总代价,给出一种归并算法,
使代价为最小。
例如有3个数,1278。
1278
12
78
|
//
\
\
|
19/
15
\/
\/
27
27
如上,归并的过程有2种:
19+27=46和15+27=42。
由此可见第二种归并方法总代价为最小。
3程序运行平台
WindowsXP、VC++6.0。
具体操作如下:
1、新建一个运算中;
2、添加后缀为c.pp的源文件;
3、在源文件中进行编程;
4、编译,链接,执行。
4总体设计
最短路径设计:
图
(1)
最优树的设计:
图
(2)
最小代价子母树的设计:
图(3)
5程序类的说明
5.1最短路径的动态规划算法
Floyd算法
实现计算完全最短路径的Floyd算法
输入:
图的权重矩阵W
输出:
包含最短路径长度的距离矩阵
D←W
fork←1tondo
fori←1tondo
forj←1tondo
D[i,j]←min{D[i,j],D[i,k]+D[k,j]}
returnD
5.2最优树的动态规划算法
输入:
一个n个键的有序列表的查找概率数组P[1…n]
在最优BST中成功查找的平均比较次数,以及最优BST中子树的根表R
OptimalBST(p[1…n])
fori←1tondo
C[i,i-1]←0
C[i][i]←P[i]
R[i,i]←i
C[n+1,n]←0
ford←1ton-1do//对角线计数
fori←1ton-ddo
j←i+d
minval←∞
fork←itojdo
ifC[i,k-1]+C[k+1,j]<
minval
minval←C[i,k-1]+C[k+1,j];
kmin←k
R[i,j]←kmin
sum←P[i];
fors←i+1tojdosum←sum+P[s]
C[i,j]←minval+sum
returnC[1,n],R
5.3最小代价子母树的动态规划算法
对fn+1(xn+1)初始化;
{边界条件}
fork:
=ndownto1do
for每一个xk∈Xkdo
for每一个uk∈Uk(xk)do
begin
fk(xk):
=一个极值;
{∞或-∞}
xk+1:
=Tk(xk,uk);
{状态转移方程}
t:
=φ(fk+1(xk+1),vk(xk,uk));
{基本方程(9)式}
ift比fk(xk)更优thenfk(xk):
=t;
{计算fk(xk)的最优值}
end;
for每一个x1∈X1do
iff1(x1)比t更优thent:
=f1(x1);
{按照10式求出最优指标}
6模块分析
6.1最短路径的动态规划模块
voidFLOYD(GRAPHg,intn,intd[][N],intp[][N])
{
inti,j,k,w;
for(i=0;
i<
n;
i++)
for(j=0;
j<
j++)
{
d[i][j]=g.edges[i][j];
if((d[i][j]<
MAXDIST)&
&
(d[i][j]!
=0))
p[i][j]=j;
else
p[i][j]=-1;
}
for(i=0;
d[i][i]=0;
for(k=0;
k<
k++)
for(i=0;
for(j=0;
if(d[i][j]>
d[i][k]+d[k][j])
{
d[i][j]=d[i][k]+d[k][j];
p[i][j]=p[i][k];
}
}
6.2最优树的动态规划模块
voidoptimal_bst(doublee[][MAXNUM],introot[][MAXNUM],doublew[][MAXNUM],intn)
{
inti=0,j=0;
//针对左或右孩子为空树情况初始化
for(i=1;
=n+1;
i++)
e[i][i-1]=q[i-1];
w[i][i-1]=q[i-1];
}
intl=0;
//计算顺序如下:
根据计算式:
e[i,j]=e[i,r-1]+e[r+1,j
//首先计算节点个数为1的最优二叉树的代价e[1,1],e[2,2]……
//接着计算节点个数为1的最优二叉树的代价e[1,2],e[2,3]……
//……
//最后计算结点个数为n的最优二叉树的代价e[1,n],利用之前保存的较少结点最优二叉树的结果。
for(l=1;
l<
=n;
l++)
=n-l+1;
{j=i+l-1;
e[i][j]=MAX;
w[i][j]=w[i][j-1]+p[j]+q[j];
for(intr=i;
r<
=j;
r++)
{doublet=0;
t=e[i][r-1]+e[r+1][j]+w[i][j];
if(t<
e[i][j])
{e[i][j]=t;
root[i][j]=t;
}}}}}
6.3最小代价子母树的动态规划模块
voidPrintResult(MIN_NODE*pNode,boolbr)
{usingstd:
:
queue;
queue<
MIN_NODE*>
aQueue;
MIN_NODE*pointer=pNode;
if(pointer)
{aQueue.push(pointer);
intlevel=pointer->
level;
while(!
aQueue.empty())
{pointer=aQueue.front();
if(level!
=pointer->
level)
{level=pointer->
printf("
\n"
);
val=%dlevel=%d|"
pointer->
minVal,pointer->
level);
aQueue.pop();
if(pointer->
pSubNode[0])
{aQueue.push(pointer->
pSubNode[0]);
pSubNode[1])
{aQueue.push(pointer->
pSubNode[1]);
}}
7系统测试
7.1最短路径的动态规划测试结果:
图(4)
图(5)
7.2最优树的动态规划
图(6)
7.3最小代价子母树测试结果
图(7)
8结论
在做这个课程设计中,关键在于对动态规划思想的了解。
这三个实际问题,在学习过的知识中,通过数据结构来实现基本算法,再通过C语言来实现程序的调试、输出结果。
对于我来说,我的这个课程设计中的最小代价子母树有点难度,最短路径为标题和最优树的求解相对容易些。
在动态规划问题求解过程,由于自己对数据结构还不太熟练,所以我也参考了一些资料。
并且不少操作需进一步完善,这次课程设计有许多不足之处,可能是因为经验还不足,对问题预期不够等一些不可预见的原因所致。
这些都是以后做课程设计的经验,我想在以后的课程设计中,我会做得越来越好。
致谢
能够完成这次课程设计首先要感谢辅导老师谢春芝老师,在课程设计中我遇到了很多的问题,谢老师都是很耐心的给我讲解,而且还教了我很多小技巧。
其次要感谢黄襄念老师,他教会我认识到算法的时间效率在现今的运用时多么的重要。
再次要感谢的是教我C语言的周立章老师,他教会了我C语言的基本语法知识以及编程技巧,使得我能够了解到C语言未来在我人生中的用途,教会我要要高瞻远瞩要掌握全局,这样才是一个优秀的程序员;
这次能够成功完成这次课程设计就是很好的证明。
最后要感谢我的同学,在编程的过程中我遇到了问题,而在此时老师也无法联系到,是我的同学帮我解决问题,指出错误让我能顺利完成这次课程设计。
再次感谢大家!
参考文献
[1]严蔚敏吴伟民著.《数据结构》(C语言版)(第三版).北京:
清华大学出版社2007.4
[2]谭浩强著.《C程序设计》(第三版).北京:
清华大学出版社;
2006.9
[3]AnanyLevitin著.潘彦译《算法设计与分析基础》(第二版).北京:
2010.1
[4][美]S巴斯著.计算机算法:
设计和分析引论.朱洪等译上海:
复旦大学出版社;
1985.1
附录
最短路径源程序:
#include<
stdio.h>
#defineN10
#defineMAXDIST9999
typedefstruct
chardata[N];
intedges[N][N];
}GRAPH;
voidDIJKSTRA(GRAPHg,intn,inti,intd[],intp[])
ints[N];
intmindist,dist;
intj,k,u;
for(j=0;
{
d[j]=g.edges[i][j];
s[j]=0;
if((d[j]<
(d[j]!
p[j]=i;
else
p[j]=-1;
}
s[i]=1;
n-1;
mindist=MAXDIST;
u=i;
if((s[k]==0)&
(d[k]<
mindist))
{
u=k;
mindist=d[k];
}
s[u]=1;
for(k=0;
if(s[k]==0)
{
dist=d[u]+g.edges[u][k];
if(dist<
d[k])
d[k]=dist;
p[k]=u;
}
voidopdijk(intv0,intn,intd[],intp[])
inti,j,k,pre;
if(i!
=v0)
printf("
\n%d"
i);
pre=p[i];
while(pre!
=-1)
printf("
<
--%d"
pre);
pre=p[pre];
if(d[i]==MAXDIST)
v0);
%d"
d[i]);
voidopfloy(intn,intd[][N],intpath[][N])
inti,j,k,c,min,next;
printf("
\n\n源点为v%d:
"
if(j!
=i)
\n%d到%d最短路径:
i,j);
next=path[i][j];
while(next!
printf("
->
next);
next=path[next][j];
if(d[i][j]==MAXDIST)
j);
\t%d"
d[i][j]);
voidmain()
GRAPHg;
inti,j,k,n;
intd[N],p[N],sd[N][N],sp[N][N];
//clrscr();
n=6;
g.data[0]='
a'
;
g.data[1]='
b'
g.data[2]='
c'
g.data[3]='
d'
g.data[4]='
e'
g.data[5]='
f'
g.edges[i][j]=MAXDIST;
g.edges[j][j]=0;
g.edges[0][2]=10;
g.edges[0][4]=30;
g.edges[0][5]=100;
g.edges[1][2]=5;
g.edges[2][3]=50;
g.edges[3][5]=10;
g.edges[4][3]=20;
g.edges[4][5]=60;
DIJKSTRA(g,n,i,d,p);
//opfloy(i,sd,sp);
opdijk(i,n,d,p);
FLOYD(g,n,sd,sp);
opfloy(n,sd,sp);
getchar();
最优树的源程序:
#include<
iostream>
usingnamespacestd;
#defineMAXNUM100
#defineMAX65536
//p中为有序关键字k1到k5的搜索概率,k1<
k2<
k3<
k4<
k5
doublep[MAXNUM]={0.00,0.15,0.10,0.05,0.10,0.20};
doubleq[MAXNUM]={0.05,0.10,0.05,0.05,0.05,0.10};
voidoptimal_bst(doublee[][MAXNUM],introot[][MAXNUM],doublew[][MAXNUM],intn)
j=i+l-1;
doublet=0;