罗马尼亚问题.docx
- 文档编号:11420682
- 上传时间:2023-02-28
- 格式:DOCX
- 页数:17
- 大小:127.63KB
罗马尼亚问题.docx
《罗马尼亚问题.docx》由会员分享,可在线阅读,更多相关《罗马尼亚问题.docx(17页珍藏版)》请在冰豆网上搜索。
罗马尼亚问题
罗马尼亚问题
一、问题描述
(1)罗马尼亚问题:
FindBuchareststartingatArad
分别用宽度优先、深度优先、贪婪算法和A*算法求解“罗马利亚度假问题”。
要求:
分别用文件存储地图和启发函数表,用生成节点数比较几种算法在问题求解时的效率,列表给出结果。
(2)附(罗马尼亚地图)
(3)附各结点启发值:
36624102341603802421001611931762537732915180226199244374
二、数据结构
1、逻辑结构:
用到线性结构包括数组、链表、栈;非线性结构:
图。
2、存储结构(物理结构):
顺序存储结构和链式存储结构
(1)启发函数表采用顺序存储结构数组data[20].存储,从文件中读入:
for(n=0;n<20;n++)
{
fscanf(fp1,"%d",&data[n]);
}
(2)图采用二维数组map[]存储,从文件中读入:
for(i=0;i<20;i++)
{
for(j=0;j<20;j++)
{
fscanf(fp2,"%d",&map[i][j]);
}
}
(3)宽度优先的fringe表采用链式存储结构存储,且每一个结点为一个包含结点序号、h、g、f值等的结构体;
(4)深度优先的fringe表采用顺序栈存储,且每一个结点为一个包含结点序号、h、g、f值等的结构体;
(5)贪婪算法和A*算法采用结构体数组存储。
3、数据的运算:
抽象数据类型
(1)定义
typedefstructfringe
{
intstate;//存储点序号信息
intg;//g值
inth;//h值
intf;//f值
intk;//标记是否已扩展
}FringeType;
(2)运算:
检索、插入、删除等运算
(3)表示:
每一个数据元素就是一个记录。
它包括学生的结点序号信息、g值、h值、f值等数据项,在解决实际应用问题时把每个记录当作一个基本单位进行访问和处理。
三、算法思想
1、宽度优先
(1)算法描述:
从Arad结点出发,判断是否为目标结点,若否,宽度优先搜索系统地探寻与该结点相连的结点,算法首先搜索和Arad距离为k的所有顶点,然后再去搜索和Arad距离为k+l的其他顶点,找出并存进待扩展结点表,等待扩展,每次先判断待扩展结点表是否为空,若否则从待扩展结点表中取出一个结点进行扩展,并将扩展后的结点存进该表,若是,则返回失败。
该算法同时能生成一棵根为Arad且包括所有可达顶点的宽度优先树。
宽度优先算法一直通过已找到和未找到顶点之间的边界向外扩展。
通过为每个顶点着色(白色、灰色和黑色)。
算法开始前所有顶点都是白色,随着搜索的进行,各顶点会逐渐被着色。
在搜索中第一次碰到,着灰色,然后是灰色。
因此,灰色和黑色顶点都已被发现,灰色顶点与一些白色顶点相邻接,它们代表着已找到和未找到顶点之间的边界。
在宽度优先搜索中,我用到单链表来存储待扩展结点表。
(2)伪代码实现:
while(fringe[]!
=NULL)
takeoutu∈fringe[]
do
coloru;
while(u≠goal)
do
expandu;
BFS()
{
for(1-20循环)
{
if(有路径存在)
{
新生成结点;
BFSnode++;
}
}
取链表的第一个结点;
if(为goal)
{returnBFSnode;}
elseif(不为goal)
{
BFS();//递归调用
}
returnBFSnode;}
putsuccessors(BFS)infringe[];
end;
end;
(3)算法评价:
宽度优先是完备的(如果分支因子有限的话),所以说,在任何情况下宽度优先都能找到一个解。
此外,最坏的情况是,当目标结点是第d层的最后一个被扩展的结点时。
时间复杂度:
(b为分支因子,d为深度)
空间复杂度:
所存储的节点的个数。
2、深度优先
(1)算法描述:
深度优先搜索是一种每次都要达到被搜索结构的叶结点的搜索方法,直到不能再深入为止,然后返回到另一个结点,继续对该结点进行深搜。
当有目标结点出现时,返回目标结点,搜索结束;否则,若待扩展结点表已空,且未找到目标结点,则返回失败,停止搜索。
同样,深度优先搜索从Arad结点出发,判断是否为目标结点,若否,探寻与该结点相连的结点,算法首先搜索一条分支上的所有顶点,然后再去搜索和Arad的其它分支结点,找出并存进待扩展结点表,等待扩展,每次先判断待扩展结点表是否为空,若否,则从待扩展结点表中取出一个结点进行扩展,并将扩展后的结点存进该表,若是,则返回失败。
该算法同时能生成一棵根为Arad且包括所有可达顶点的深度优先树。
在深度优先搜索中,我用到堆栈来存储待扩展结点表。
(2)伪代码实现
while(fringe[]!
=NULL)
takeoutu∈fringe[]
do
coloru;
while(u≠goal)
do
expandu;
DFS()
{
for(1-20循环)
{
if(有路径存在)
{
新生成结点;
DFSnode++;
}
}
出堆栈;
if(是目标结点)
{
returnDFSnode;}
else
{
DFS();//递归调用
}
returnDFSnode;
}
putsuccessors(DFS)infringe[];
end;
end;
(3)算法评价:
不是完备的(除非查找空间是有限的)。
同时,也不能找到最优解。
时间复杂度:
空间复杂度:
(b为分支因子,m为深度,仅有一枝需要存储)
3、贪婪算法
(1)算法描述:
贪婪算法是指,在对问题求解时,总是做出在当前看来是最好的选择。
贪婪算法不从整体最优上加以考虑,所做出的仅是在某种意义上的局部最优解。
贪婪算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
在解决罗马尼亚度假问题时,贪婪算法通过比较每个待扩展结点的h值,即启发函数生成的到目标结点的启发函数值,选取一个最小的,来确定当前要扩展的结点,并将生成的结点放进fringe结点表。
在贪婪算法中,我用到结构体数组存储待扩展结点表。
(2)伪代码实现:
while(fringe[]!
=NULL)
takeoutu∈fringe[]
do
coloru;
while(u≠goal)
do
expandu;
greedy()
{for(1-20循环)
{
if(有路径)
{
新生成结点
GNode++;
}
}
for(循环)
{
if(比较h值大小)
{
找出最小的h值结点;
}
}if(离目标的实际值!
=0)
{
greedy();//递归调用
}
returnGNode;//生成结点数
}
putsuccessors(greedy)infringe[];
end;
end;
(3)算法评价
不是完备的。
同时,找到的解也不一定是最优解。
时间复杂度:
(b代表分支数,m为深度)
空间复杂度:
)
4、A*算法
(1)算法描述:
A*算法用公式表示为:
f(n)=g(n)+h(n),其中f(n)是从初始点经由结点n到目标点的估价函数;g(n)是在状态空间中从初始节点到n节点的实际代价,h(n)是从n到目标节点最佳路径的估计代价。
A*能找到最优解的条件,关键在于估价函数h(n)的选取;若估价值<实际值,则能保证得到最优解。
(2)伪代码实现:
while(fringe[]!
=NULL)
takeoutu∈fringe[]
do
coloru;
while(u≠goal)
do
expandu;
Astar()
{
for(循环)
{
if(有路径存在0)
{
新生成结点;
ASNode++;
}
}
for(循环)
{
if(f值比min小)
{
找出最f值最小的结点扩展;
}
}
for(循环)
{
if(为目标结点)
{
returnASNode;
}
}
Sstar();//递归调用
returnASNode;
}
putsuccessors(Astar)infringe[];
end;
end;
(3)算法评价:
完备的,能够找到最优解;
时间复杂度:
扩展节点的数目;
空间复杂度:
所有生成的结点。
四、运行结果:
宽度优先、深度优先、贪婪算法、A*算法:
五、比较结论:
通过比较,DFS和Greedy搜索生成的结点数目最少,为9个,效率最高;BFS生成的结点数目最多,为19个,效率最低。
但是DFS、BFS和Greedy搜索找到的都不一定最优解,只有A*算法具有完备性且始终找到的都是最优解。
宽度优先虽然是完备的(如果分支因子有限的话),在任何情况下宽度优先都能找到一个解,但是,它找到的第一个解并非最优的,此外,最坏的情况是,当目标结点是第d层的最后一个被扩展的结点时,它将耗费大量的时间。
宽度优先时间复杂度:
(b为分支因子,d为深度);空间复杂度为所存储的节点的个数。
DFS不是完备的(除非查找空间是有限的),同时,它也不能找到最优解。
深度优先的时间复杂度:
;空间复杂度:
(b为分支因子,m为深度,仅有一枝需要存储)。
贪婪算法不是完备的。
同时,它找到的解也不一定是最优解。
其时间复杂度:
(b代表分支数,m为深度);空间复杂度为
)。
所以只有A*算法是完备的,且能够找到最优解;其时间复杂度:
扩展节点的数目;空间复杂度:
所有生成的结点。
综合来看,DFS和贪婪算法的效率较高,但解并非最优,而A*算法的效率稍逊色,但解为最优;而BFS搜索则效率最低,且不一定为最优解。
n皇后问题
一、问题描述:
(1)n皇后问题:
在n*n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,
(2)分别用回溯法(递归)、爬山法和GA算法求解n皇后问题。
要求:
输入n,并用运行时间比较几种算法在相同规模的问题时的求解效率。
列表给出结果。
二、数据结构
1、逻辑结构:
用到线性结构包括数组queenList[col]等。
2、存储结构(物理结构):
顺序存储结构。
3、数据的运算:
(1)表示:
(queenList[col],col)表示(row,col)的皇后
(2)运算:
检索、插入、删除等运算
三、算法思想:
1、回溯法
(1)算法描述:
回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。
但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法。
(2)伪代码实现:
基本思想是:
从一条路往前走,能进则进,不能进则退回来,换一条路再试。
对于n皇后问题,第一步按照顺序放一个皇后,然后第二步符合要求放第2个皇后,如果没有符合位置符合要求,那么就要改变第一个皇后的位置,重新放第2个皇后的位置,直到找到符合条件的位置就可以了,在目标状态终止。
(3)算法评价
回溯法在皇后数目较小的,很占优势,它的速度非常的快,但随着皇后数目的增加,回溯法显得很不实用,在n=28时,用回溯法已不能较好的解决n皇后问题。
2、爬山法
(1)算法描述:
爬山法是指从当前的节点开始,和周围的邻居节点的值进行比较。
如果当前节点是最大的,那么返回当前节点,作为最大值(既山峰最高点);反之就用最高的邻居节点来,替换当前节点,从而实现向山峰的高处攀爬的目的。
如此循环直到达到最高点。
每次都选择是与目标结点启发函数值最小的那个结点,经过迂回前进,最终达到解决问题的总目标。
如果我们把目标函数的几何图形看成一个山峰,那么点的直接移动就像人在爬山,选择方向,逐步向山顶移动。
爬山法需要建立一个描述数据库变化的单极值函数,且使极值对应目标状态;选取使函数值增长最大的那条规则作用于数据库;重复上步,直到没有规则使函数值继续增长。
爬山法是一种局部搜索算法,也属一种启发式方法。
但它一般只能得到局部最优,并且这种解还依赖于起始点的选取。
它是一种解多变量无约束最优化问题的一类方法,通过点的直接移动产生的目标值有所改善的点,经过这样的移动,逐步到达使目标函数最优的点。
在爬山法中,h表示相互攻击的皇后的对数,用它来生成启发函数。
(2)伪代码实现:
爬山函数(问题)是局部极大值的一种状态返回
输入问题,一个问题
局部变量:
当前,一个节点。
邻居,一个节点。
当前生成节点(初始状态[问题])
循环做
邻居一个价值最高当前的继任者
如果值[邻居]≤价值[当前],然后返回状态[当前]
当前邻居
(3)算法评价
爬山法的缺点:
会出现山脊、高原,86%的时间会卡住;但是爬山算法较简单,在皇后的个数较多时体现出来效率最高,处理多约束大规模问题时往往不能得到较好的解。
3、遗传算法
(1)算法描述:
遗传算法(GeneticAlgorithm)是模拟物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。
对于一个求函数最大值的优化问题,首先初始化,包括种群的大小,编码的方案,遗传的代数,变异的概率,等等;然后进行选择操作;接着是将选择的个体进行交叉;然后再进行选择,并将选择的个体进行变异;最后就是更新最优值了。
(2)伪代码实现:
函数GA(总群,最适合的FN)返回一个个体
输入:
人口,个体
最适合的FN,一个函数,它决定了个体素质
循环
新_种群空的集合
从1到大小(人口)做i次
X随机选择(人口,最适合的FN)
Y随机选择(人口,最适合的FN)
孩子再生(X,Y)
(随机概率小),那么孩子变异(孩子)
孩子添加到新_种群
人口新_种群
直到有个体适合足够或足够的时间耗完
返回最佳个体
大概分为:
初始化、选择运算、不停的交叉运算、终止计算。
(3)算法评价
遗传算法优点是能很好的处理约束,能很好的跳出局部最优,最终得到全局最优解,全局搜索能力强;缺点是收敛较慢,局部搜索能力较弱,运行时间长,且容易受参数的影响。
四、运行结果:
n=10时;
1、回溯法:
2、爬山法
3、遗传算法:
n=20时;
1、回溯法:
2、爬山法
3、遗传算法:
五、比较结论:
回溯法在皇后数目较小的,很占优势,它的速度非常的快,但随着皇后数目的增加,回溯法显得很不实用,在n=28时,用回溯法已不能较好的解决n皇后问题。
爬山法是一种始终都比较快的算法,它的运行时间与皇后是个数没有必然的联系,而且在n很大时,它显现出来运行时间短,效率高的优势,但它的缺点是会出现山脊、高原,86%的时间会卡住。
总的来说,爬山算法较简单,也比较快,在皇后的个数较多时体现出来效率最高,处理多约束大规模问题时往往不能得到较好的解。
遗传算法优点是能很好的处理约束,能很好的跳出局部最优,最终得到全局最优解,全局搜索能力强;缺点是收敛较慢,局部搜索能力较弱,运行时间中等,且容易受n值的影响。
遗传算法的运行时间在n很小时没有回溯法快,但是随着n值的增加,遗产算法的优点也就显现出来,它能够解决回溯法不能解决的问题。
总的来说,回溯在n值很小时,效率最高,在n值很大时,回溯法不能再解决,此时,爬山法的效率最高,且与n值没有必然的联系,遗传算法次之。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 罗马尼亚 问题