算法分析与设计报告.docx
《算法分析与设计报告.docx》由会员分享,可在线阅读,更多相关《算法分析与设计报告.docx(21页珍藏版)》请在冰豆网上搜索。
算法分析与设计报告
中国地质大学
研究生课程论文封面
课程名称算法分析与设计
教师姓名
研究生姓名
研究生学号
研究生专业计算机技术
所在院系计算机学院
类别:
B.硕士
日期:
2014年1月8日
对课程论文的评语
平时成绩:
课程论文成绩:
总成绩:
评阅人签名:
注:
1、无评阅人签名成绩无效;
2、必须用钢笔或圆珠笔批阅,用铅笔阅卷无效;
3、如有平时成绩,必须在上面评分表中标出,并计算入总成绩。
第一章算法导引
1.1算法算法:
用计算机求解问题的步骤、规则内存空间——>初始状态—————>终止状态有限状态机算法的五个特性:
输出:
一个算法产生一个或多个输出从内存——>认识状态输入:
一个算法有0个输入或多个输入inputa,b
无二义性:
算法的每一种运算必须要有确切的定义,即每一种运算应该执行何种动作必须是相当清楚的、无二义性的(人和计算机、智能、确定的、机器;人机象棋:
搜索)。
能行性:
(1)人能做,机器没法做:
能够形式化,没有办法写出算法
(2)股票预测、彩票:
模型
有限性:
可计算问题、有限的、可忍耐算法设计:
自动化、自动程序设计、公式发现、公式挖掘、知识发现算法验证:
设计—表示(语言)—确认—分析—测试程序
1.2算法分析数学模型:
1.串行算法,冯诺依曼机
2.均匀存贮,存贮空间足够大
3.基本运算时间确定基本概念:
1.问题规模:
与参数有关
2.频率计数不分析算法具体执行时间,分析问题复杂性:
问题规模增大时的规律根据复杂性,将算法分为两类:
1.多项式时间算法P:
C,logn,n,nlogn,n2(理论上可行,实际上也可行)
2.指数时间算法NP:
2n,n!
nn(理论上可行,实际上不可行)
O(l)O(2n))降低算法设计复杂度分析算法时间与问题规模:
确定f(n)=0(g(n))上界和f(n)=Q(g(n))下界
1.3小结老师首先带领我们回顾了本科阶段的算法基础相关知识,对于没有系统学习过算法知识的我来说,更是一种知识入门,使我对这门课程有一些初步的了解。
然后在对算法进行分析时,不分析算法具体的执行时间,而是分析问题的复杂性(问题规模增大时的规律)。
根据算法的特点可以将要求解的问题分为两类:
离散型和连续型。
离散型问题需要讨论问题的规
模,如果是多项式时间复杂度则称为P问题;如果是指数时间复杂度则称为NP问题。
对于
连续型问题,需要讨论算法的收敛性。
第二章分治法
2.1一般方法
在求解问题时,为了将问题简化,将实际问题转变为数学问题,将数学问题转变为代数问题,将代数问题转变为解方程问题,将解方程问题转变为解线性方程组问题。
求解问题的技术:
1.化难为易的校正技术:
例如求f(x)=a-x2=0;
2.化粗为精的松弛技术:
直接法,间接法,例如求圆的面积(割圆法)
3.化大为小的缩减技术:
f(n)=n*f(n-1),f
(1)=1问题性质不变
分治法的思想:
将整个问题分为若干个小问题分而治之,问题的性质不变。
它的求解可用一个递归过程来表示。
2.2二分检索
已知一个按非降次序排列的元素表ai,a2,…,an,要求判定某给定元素x是否在该表中
出现。
问题规模0(logn)
2.3归并分类(排序)
Proceduremergesort(low,high)iflowthen
mid|(low+high)/2
call
mergesort(low,mid)
call
mergesort(mid+1,high)
call
mergesort(low,mid,high)
endif
问题规模
0(ngn)
2.4快速分类反复对产生的文件进行划分
2.5斯特拉森矩阵乘法
Am*lBl*nCm*n问题规模0(n3)
2.6小结
分治法是一种用空间换时间的技术,通过将大规模的问题划分为小规模问题进行求解来降低求解难度,采用分治技术,问题首先必须能够分解,而且分解后,问题的性质并没有发生变化。
采用分治技术的目的只是并行算法设计,降低算法时间复杂度。
在本章老师主要讲解了分治法的基本递归求解,二分检索、归并分类、快速分类、斯特拉森矩阵乘法以及它们的时间复杂度的求解。
第三章贪心法
3.1一般方法
概念:
有n个输入,问题的解是这n个输入的一个子集,子集满足一组条件(约束条件),子集可能有很多,满足条件的子集叫做可行解,根据问题,人们设计一个函数,通过函数极值的计算,找到一个最优的可行解,叫做最优解。
离散优化问题
连续函数优化问题的分类:
1.函数优化问题:
f(x):
高维、非线性、不连续、没有明确的解析式;这类问题的求解方法有:
解方程法、迭代法(最速下降法、共轭方向法、牛顿迭代法等)、随机优化(演化计算)等。
2.模型参数优化:
此类问题的求解方法一般是:
根据所给问题或者曲线,然后预测方程,对预测方程中的参数进行优化求解。
3.模型发现问题:
自动程序设计,一般是输入散点,要求给出拟合曲线。
解决方法有基因表达式程序设计等。
优化问题分类:
1.有约束优化与无约束优化
2.线性优化与非线性优化
3.静态优化与动态优化(实时性)
4.确定性优化与随机优化
5.单目标优化与多目标优化(矛盾或不协调的)贪心算法是一种分级处理方法,它根据问题性质找到一种度量标准
3.2背包问题
部分背包问题的数学模型为:
假设背包容量为m,有n件物品,每种物品i的重量为
Wi,其效益值为pi,问如何装包,在背包的容量范围内装出的值最多。
n
maxxipi
i1
n
xiwiM
i1
Xi€{0,1}0/1背包问题
Xi€[0,1]部分背包问题
老师以书上的题目为例,根据按效益值由大到小的装、按质量由小到大的装和按单位质量效益值由大到小的装(Pi/Wi)三种方法来寻找最优解。
经过计算可知按单位质量效益值由大到小的装包获得的结果最好。
3.3最小生成树问题
设G=(V,E)是一个无向连通图,如果G的生成子图T=(V,E')是一棵树,则称T是G的一棵生成树。
根据边成本由小到大排序,找到最优的生成树。
3.4小结
贪心算法适用于求解从给定的n个输入中找到一个满足约束条件的子集的问题。
满足约束条件的子集称为可行解,满足目标函数的可行解称为最优解。
用贪心算法求解问题的关键在于找出求解问题的量度标准。
本章老师主要讲了贪心算法的适用领域,详细讲解了背包问题及最小生成树的算法及其时间复杂度的求解。
为了便于学生理解,老师联系自己曾经做过的毕业设计的凸多边形问题,讲述了是如何对问题进行分析和寻找解决方案的,而且讲解了为何贪心算法无法用于求解凸多边形问题,使同学们更好的领悟和体会贪心法的应用范围。
第四章动态规划
4.1一般方法求解优化问题的方法:
1.多阶段决策:
可以把问题分成若干阶段
2.最优性原理:
无论过程的初始状态和初始决策是什么,决策所产生的状态构成一个最优决策序列(找到一个递推关系式)
4.2多段图问题多段图G=(V,E),求源点s到汇点t的最短路径设cost(i,j)表示从源点到第i个阶段的j点的最短路径:
cost(i,j)lmVin{cost(i1,l)c(l,j)}lVi1
l,jE
设Bcost(i,j)表示从第i个阶段的j点到汇点的最短路径:
Bcost(i,j)min{bcost(i1,l)c(l,j)}
lVi1
l,jE
4.3每对结点之间的最短路径
单源最短路径问题O(n2)任意两点间最短路径问题O(n3)
设Ak代表i,j两个结点间考虑了1-k结点时最短路径,
A0(i,j)=C(i,j)
An(i,j)=min{An-1(i,j),An-1(i,n)+An-1(n,j)}
Ak(i,j)=min{Ak-1(i,j),Ak-1(i,k)+Ak-1(k,j)}
4.4最优二分检索树
4.5
检索成本的计算方法:
其余的决策都必须相对于初始
A0(i,j)就是成本矩阵
设aiak
总成本:
C(0,n)
min{C(0,k1)C(k,n)
1kn
P(k)w(0,k1)w(k,n)}
C(0,n)
mknn{c(o,k
1)
C(k,n)}
w(0,n)
比较运算
n次耗时
C(i,j)
.miirj{C(i,k
1)
C(k,j)
P(k)w(i,k1)
w(k,j)}
C(i,j)
min{C(i,k
ikj
1)
C(k,j)}
w(i,j)
cost(L)C(0,k1)cost(R)C(k,n)
4.5矩阵连乘问题:
1234
求最小计算量。
MMMM10*200,假设r°=10,门=30,「2=70,心=1,"200,
矩阵连乘问题满足以下公式:
l
Am*lBl*nCm*n,Cij
ai*F
k1
^bk*j
根据分析,得到递推公式:
D(i,j)叫in{D(i,k)
ikj
D(k
1,j)A山几}
D(i,j)表示M'M'讪‘2
Mj
最优的次数
D(1,n)1njiri{D(1,k)
D(k
1,n)巧小}
据此得到结果:
0
21000
2400
4400
1
0
2100
8100
1
2
0
14000
3
3
3
0
4.60/1背包问题
设fj(x)表示将第1至j件物品装入容量为x的包所获得的最大效益值。
fj(x)max{fj!
(x),fj(xWj)Pj}
fj-1(x)表示前面已装满的情况下的效益值,fj(x-Wj)+Pj表示将第j件物品装进去后的效益
值,两者取最大者为最终结果。
fj(x)fji(x),Xj0
fj(x)fj(xWj)Pj,Xj1
老师以书上题目为例,为大家讲解整个求解过程,题目为:
n=3,(Wi,W2,W3)=(2,3,4),
(P1,P2,P3)=(1,2,5),M=6。
部分背包问题
同样的n件物品,Xi€{x|0wxw1},部分背包情况下获得的效益值为Pi,0/1背包情况下获得的效益值为P2,部分背包情况下减去小数部分的效益值为P3,三者满足关系Pi>
P2》P30
4.7TSP问题
有n个城市,城市之间距离用C(i,j)表示,从编号为1的城市经过其他的n-1个城市一次且一次,回到城市1,路径最短。
图中任意两点间最短路径0(n3)
静态TSPC(n,n)不变(O(n!
))
动态TSPCt(n,n)随时间变化,实时
(动态)多目标TSP:
C(n,n),Cj={a13},速度快、成本低
设g(i,S)代表从i点出发经过S中的(S是城市编号的集合)所有城市后回到1的最大
路径,最终求:
g(1,S)mi^Gig(i,S{1})}g(i,S)mnin{Cjg(j,S{j})}S{2,3,4,,n}
iSjS
0
10
15
20
5
0
9
10
6
13
0
12
8
8
9
0
4.8子集和数问题:
设有n个正整数{ai,a2,…,an},求和为M的一个子集。
4.9调度问题:
1.相同处理机的调度
设有{tl,t2,…,tn}有相同的设备两台,让你给出调度模式调度这n个任务
2.流水线调度问题
两个设备的流水线调度问题:
P问题(排序问题)
三个设备的流水线调度问题:
NP问题
S={tl,t2,…,tn},g(S,O)
可得递推公式:
g(S,0)mingg(S{t},bj}(ai,t都结束才可以调度bi)
tjS
根据问题所要求的解的不同,可以将这些问题分为三类:
1•求解整数规划类问题。
要求自变量为整数,即最终结果是要求给出整数解集合的一个选择。
例如:
多段图问题和0/1背包问题。
2•求解最优结构。
要求最终结果是给出一棵最优二分树的结构。
例如:
最优二分检索树和矩阵连乘问题。
3.序列优化问题。
要求最终结果是找出最优的一个排列。
例如:
TSP问题和调度问题。
4.10小结
动态规划方法一般用来求解优化问题。
使用该方法求解的问题主要有两个特点:
多阶段
决策,可以把问题分为若干个阶段;满足最优性原理,当前状态和决策只和它前一阶段的状
态有关,和前一阶段的状态和决策如何得到无关。
用动态规划求解问题,关键在于找到求解
问题的一个递推关系式。
本章内容很多,同时又很重要,老师详细的为我们讲解了如何利用
动态规划技术求解多段图问题、任意两点间最短路径问题、最优二分检索树、矩阵连乘问题、0/1背包问题、TSP问题和调度问题,并详细讲解了如何构造与使用递推关系式来解决这些问题。
对于每一个问题,老师都通过讲解书上的实例来加深我们对算法理解和认识,也让我
们更清楚如何利用算法解决相关问题。
用动态规划技术解决矩阵连乘问题是老师课外拓展的内容。
老师还向我们简单介绍了子集和数问题,它与0/1背包问题、TSP问题、3-Sat问题
都属于NP问题,想要求解它们,就要找到合适的方法将它们化简为P问题。
另外,对于本
章用动态规划解决的几类问题,老师也带我们进行了归类总结,更加深了我们对动态规划技术的印象。
第五章基本检索与周游方法
5.1一般方法
1.树的检索
二叉树检索(先根、中根、后根)以下图为例:
宽度优先:
①②③④⑤⑥⑦⑧
深度优先:
①②④⑧⑤⑥③⑦
5.2双连通分图和深度优先检索
双连通、单连通、关节点
识别关节点:
根节点有几个儿子
叶子节点肯定不是关节点
中间节点:
从它每个儿子出发往下走,能经过边到达它的祖先节点。
计算每一个节点的深度优先数DFN(x),最低深度优先数L(x)。
5.3对策树(博弈树)
每个节点,状态评估函数E(x)
max-min过程
max(f)A;min(f)B
a截断:
如果一个求最小值位置的值被判断为小于或等于它父亲的a值,那么可以停
止生成这个求最小值位置的其余儿子的值。
B截断:
如果一个求最大值位置的值被判断为大于或等于它父亲的B值,那么可以停止
生成这个求最大值位置的其余儿子的值。
a-B截断:
对于任一结点x,设B是该结点父亲的B值且D=-B,那么如果x的值判断为大于或等于D,则可以停止生成x的其他儿子。
老师以书上题目为例,通过一种假想的博弈游戏,为我们讲解了a-3截断的使用方法。
5.4小结
基本检索与周游方法一般是针对树、图这样的数据结构。
对数据结构的操作即为算法的
设计与分析。
老师首先带领大家回顾了树的搜索策略和图的周游策略。
老师通过一个实例详
细讲解了如何将一个已有的图变为一个双连通图;详细讲解了决策树问题,决策树要求非常
有限的结点和层数;对于有限次博弈游戏所有可能的实际战例或者有限步之内的战例可以用一颗决策树表示,每一个结点表示一种战例,而对于一些博弈游戏(例如:
国际象棋)来说,构造的决策树相当大,因此我们只需要构造有限步骤的决策树,并且用一些剪枝策略减去对
自己不利的部分,这里老师详细讲解了a-B剪枝算法。
第六章回溯法
6.1一般方法
在本章内容开始时,老师将问题的求解技术进行了总结:
对于连续问题,有连续性、容易判断大小,可以利用搜索技术、领域变换规则进行求解;对于离散问题(子集和数),通过初始状态引导出最终状态,需要的方法更复杂。
离散问题
连续问题
问题「
子集和数
x2-2=0
问题状态
(0,0,0,0)
(1)
求解方法
贪心算法(量度标准)动态规划(递推关系式)通过构造解空间树
直接法(数学分析)通过领域变换(迭代法)
根据问题的性质和规范函数要求,找出限界函数、问题的上下界
深度优先+限界函数=回溯法
宽度优先+限界函数=分枝限界法
1.问题描述:
求一个n元组(xi,X2,…,Xn),Xi€Si,||Si||=ni。
2•问题状态:
一个元组,要求的参数的集合有两种表示方法:
元组长度固定:
(0,0,0,0);
元组长度不定:
(ai),(ai,a4);
3.解空间树(状态空间树):
用树的结构表示
4.解状态:
与表示方法有关
5.答案状态
6.20/1背包问题
老师以书上题目为例,P=(11,21,31,33,43,53,55,65),w=(1,11,21,23,33,43,45,55)
下图为回溯法求解0/1背包问题所生成的树:
6.3小结
回溯法一般用于求解n元组问题。
求解方法有两种:
部分解和完全解。
所需要的求解结构为状态空间树结构,将回溯过程用树的形式表达。
老师以0/1背包问题为例讲解了如何利用回溯法求解问题,并讲解了树结点的得出,以及剪枝(限界函数)的策略。
在回溯状态空间树结构中加入限界函数,可以尽可能少的检索树结构结点,尽快找到解结点。
第七章分枝-限界法
7.1一般方法
(xi,X2,•…,Xn),Xi€Si
状态及状态转移
深度优先
宽度优先
计算:
基于规则的一组符号变换过程
7.2LC分枝-限界求解
老师以书上题目为例,通过0/1背包问题和TSP问题,为我们讲解了LC分枝-限界方
法:
对于0/1背包问题,我们利用两个函数来为成本函数c(x)限界,前者为将包装满时的
成本估计函数,后者为舍弃分数尾时的上界函数,使它们对于每个结点x,都满足以下式子:
c(x)c(x)u(x)
利用这两个函数,可以获得最优的结果。
对于TSP问题,同样是利用两个函数限界,结合成本矩阵和归约矩阵获得最终的结果。
搜索方法(状态转移方法)
确定性方法:
1.解析法:
非线性方程组求解
直接法:
基于梯度、grad导数
间接法:
变成线性方程组、迭代
2.规划:
整数规划:
0/1背包
动态规划:
多段图
3.枚举法(遍历)
宽度优先
深度优先
4.剪枝法
基于状态树概念:
a-B截断、限界函数
随机性方法:
盲目搜索:
概率算法
导向搜索:
演化算法、禁忌搜索
7.3小结
分枝-限界方法是利用广度优先的方法来构造状态空间树。
老师首先以0/1背包问题为
例讲解如何通过分枝-限界法构造一个状态空间树,计算每个结点的上界和下界,以及如何生成新结点。
然后又以TSP问题为例讲解了如何利用分枝-限界法,结合构造状态空间树、成本矩阵和归约矩阵,找到解决TSP问题的一个最优组合排列。
比较动态规划方法与分枝
限界法解决TSP问题的效果,虽然两种方法计算复杂度的最坏情况是一样的,但是对于许多
具体实例而言,分枝-限界算法要比动态规划技术所用的时间少得多。
第八章程序设计
因为本人曾在完成毕业设计时了解过有关TSP问题的求解方法,因此,当老师布置本课
程的程序设计题目时,我选择了利用动态规划技术求解TSP问题。
根据动态规划算法需要求g(i,S)。
以4个城市为例,需要求出g(i,S),i取值从1到3,
S取值为{{},{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}},也就是集合{1,2,3}的所有子集合,而所有的
子集合可以用二进制数表示。
如果数在集合中,为二进制1,否则为0,数字大的在高位,如{1,2,3}表示成111,也就是7。
{3}表示成100,也就是4。
这样可以把集合映射成数组的下表,同时通过C语言的位操作来完成判断元素是否在集合中等操作,所以算法的过程就是计算二维表(n*2A(n-1))的过程。
源代码如下:
#include
#include
#include
#include
#defineMAXCOST99999intmin(intfirst,intsecond)
{
returnfirstfirst:
second;
}
intmain(intargc,char*argv[])
{
intnCity=0;
printf("pleaseenterthenumberofcities:
\n");
scanf("%d",&nCity);
int**cost=(int**)malloc(sizeof(int*)*nCity);
for(inti=0;icost[i]=(int*)malloc(sizeof(int)*((int)pow(2.0,nCity-1)));memset(cost[i],0,sizeof(int)*((int)pow(2.0,nCity-1)));
}
int**distance=(int**)malloc(sizeof(int*)*nCity);
for(inti=0;idistance[i]=(int*)malloc(sizeof(int)*nCity);
}
printf("pleaseenterthedistancebetweencities:
\n");
for(inti=0;ifor(intj=0;j}
}
//初始化g(i,{})
for(inti=1;icost[i][0]=distance[i][0];
}
for(inti=1;i<(1<<(nCity-1))-1;i++){
for(intj=1;jif(((1<<(j-1)&i)>>(j-1))==0){//判断i是否在S中,防止重复
//求出S中包含的元素和元素的个数
intcounter=0;
int*set=(int*)malloc(sizeof(int)*nCity);
for(intk=0;kif(((i>>k)&1)==1){
set[counter]=k+1;counter++;