算法分析与设计.docx
《算法分析与设计.docx》由会员分享,可在线阅读,更多相关《算法分析与设计.docx(16页珍藏版)》请在冰豆网上搜索。
算法分析与设计
算法分析与设计
2015~2016学年第二学期
学院
专业
学号
姓名
指导教师
A*算法解决旅行商问题
1、问题描述
旅行商问题:
给定一个完全无向带权图G=(V,E),其每条边(u,v)∈E有一非负整数权值w(u,v)。
要求找出G的一条经过每个顶点一次且仅经过一次的回路,使得该回路上所有边的权值之和尽可能地小。
2、算法分析及流程图
1、算法概述
A*算法是基于估价函数f(x)的一种加权状态图启发式搜索算法。
A*算法的核心是估价函数f(n)它包括g(n)和h(n)两部分。
g(n)是已经走过的代价h(n)是n到目标的估计代价。
A算法限制其估价函数中的启发函数h(x)满足对所有的节点x均有h(x)≤h*(x)其中h*(x)是从节点x到目标节点的最小代价(若有多个目标节点则为其中最小的一个)[1]。
2、A*算法伪代码
Best_First_Search()
{
Open = [起始节点];
Closed = [];
while (Open表非空)
{
从Open中取得一个节点X,并从OPEN表中删除。
if(X是目标节点)
{
求得路径PATH;返回路径PATH;
}
for(每一个X的子节点Y)
{
if(Y不在OPEN表和CLOSE表中)
{
求Y的估价值; 并将Y插入OPEN表中;
} //还没有排序
else if (Y在OPEN表中)
{
if(Y的估价值小于OPEN表的估价值) 更新OPEN表中的估价值;
}
else //Y在CLOSE表中
{
if (Y的估价值小于CLOSE表的估价值) [2]
{
更新CLOSE表中的估价值;
从CLOSE表中移出节点,并放入OPEN表中;
}
} 将X节点插入CLOSE表中; 按照估价值将OPEN表中的节点排序;
}//end for
}//end while
}//end func
3、A*算法对旅行商问题分析
以城市数5为例具体分析:
(1)输入城市数,以及城市间代权。
首先旅行商选择A->C,即表中现在有了2个元素(A,C),接下来判断下一节点的选择需要依据f(B)f(D)f(E)的大小,优先选择小的。
据分析在下一步走完的时候,旅行商已经到过3个城市,即现行状态表的元素个数均为3,距离目标还有3个城市,包括返回A的路程,根据输入数据,我们假设剩下三个城市的平均距离等于最小距离8,则从B、D、E到达目标付出的代价不小于3*8=24,即h(B)=h(D)=h(E)=24,代入函数求f。
依据公式
f(B)=g(B)+h(B)=31+24=55
f(D)=g(D)+h(D)=27+24=51
f(E)=g(E)+h(E)=29+24=53
由此得到旅行商下一步要走向D城市,所设函数为
h=(目标状态表元素-现行状态表的元素数)*k
K为一个系数,如k取两城市间最小,且h4、算法流程图
3、关键代码及实验结果
1、关键代码
boolAStar(NodeState&node,Mapmap)
{
//递归出口
if(node.cityNum==map.num)//路径满
{
node.roadLen+=getLen(node.city,0,map);
returnfalse;
}
intl=map.num-node.cityNum;//剩下的城市数
int*nextCitys=(int*)malloc(sizeof(int)*l);
getNext(node.road,nextCitys,map.num);//得到剩下城市名(索引)
//初始化子节点
for(inti=0;i{
node.children[i]=(NodeState*)malloc(sizeof(NodeState));
//分配一个子节点内存
initNode(node.children[i],map.num);//初始化子节点
cpyRoad(node.children[i]->road,node.road,map.num);
//获得之前走过的路径
node.children[i]->road[nextCitys[i]]=node.cityNum+1;
//在路径上加上该子节点
node.children[i]->city=nextCitys[i];
node.children[i]->cityNum=node.cityNum+1;//该节点顺位
node.children[i]->roadLen=node.roadLen+getLen(node.city,node.children[i]->city,map);//新的路径长度
node.children[i]->f=node.children[i]->roadLen+nearest(node.road,map);//计算估价值最后一个节点f值不准
}//根据估价值排序
sortNode(&node,l);
//向下搜索
booltoFind=true;//是否继续搜索
for(inti=0;i{
if(toFind)//发现结果就不用继续递归了
toFind=AStar(*node.children[i],map);
}
returntoFind;
}
2、运行结果
(1)城市数为3
(2)城市数为5
4、总结
通过使用A*算法对旅行商问题的探究, 了解学习了A*这种智能算法A*算法在理论上目前是解决最短路径时间最优的,但是也有缺点:
它的空间增长是指数级别的。
但确切来讲,A*算法只能求解较优的解,并比一定是最优的,A*算法具有高效性。
5、参考文献
[1]李祥,A*算法2007
[2]雷德明,严新平 .多目标智能优化算法及其应用[M].2009.科学出版社
6、附录代码
头文件:
Astar.h
//********************************************
//代码目的:
用A*算法解决旅行商问题
//
//估价函数:
f=g+h其中g为该节点走过的路程,h为未走过的节点到起点(终点)距离中最短的那个
//
//实现的几个关键数据结构:
//路径用NodeState中的road数组表示ABCDEF。
。
对应于数组的索引012345。
。
。
,数组内容表示路径顺序,若没走过定义为0
//各个城市之间的距离用Map中的rec一维数组表示,这里i城市到j城市距离为rec[j*n+i]只使用下半矩阵(副对角线)i//********************************************
#ifndefASTAR_H
#defineASTAR_H
#include
#include
#include
#defineSTRING"ABCDEFGHIJKLNMOPQRSTUVWXYZ"
#defineMAXNUM2000
//状态节点
typedefstructNodeState{
int*road;//路径
introadLen;//走过的路程
intf;//估价函数
intcityNum;//所走的城市的数目
intcity;//该节点代表的城市
NodeState**children;//指向子节点列表的指针
}NodeState;
//各个城市之间的距离矩阵
typedefstructMap{
intnum;//城市的个数
int*rec;//距离矩阵用一维表示二维
}Map;
//初始化节点初始化所有参数,对子节点列表和road设置长度
voidinitNode(NodeState*node,intn);
//A*算法主体调用完成后构造出一颗最优解搜索树
boolAStar(NodeState&node,Mapmap);
//获得下个城市可能的所有编号为road的大小
voidgetNext(introad[],intnextCitys[],intn);
//获得剩下路径到终点最近的距离
intnearest(introad[],Mapmap);//
//获得两个城市之间的距离
intgetLen(inti,intj,Mapmap);
//输入获得距离矩阵
MapinputMap();
//复制路径复制数组
voidcpyRoad(intdis[],intsrc[],intlen);
//根据估价值排序
voidsortNode(NodeState*p,intl);
#endif
display.h
#ifndefDISPLAY_H
#defineDISPLAY_H
#include"Astar.h"
voidshowRoad(int*road,intn)
{
int*sort=(int*)malloc(sizeof(int)*n);
for(inti=0;i{
sort[road[i]-1]=i;//按照顺序排位
}
for(inti=0;i{
printf("%c->",STRING[sort[i]]);
}
printf("A\n");
}
voiddisplay(NodeStatehead,intn)
{
if(head.cityNum==n)//找到最后的节点
{
showRoad(head.road,n);
printf("路径总代价为:
%d\n",head.roadLen);
}
for(inti=0;i{
if(head.children[i]!
=NULL)
{
display(*head.children[i],n);
}
}
}
#endif
源文件
Astar.cpp
#include"Astar.h"
//根据估价值排序
voidsortNode(NodeState*p,intl)
{
intn=l;
for(inti=0;i{
for(intj=0;j{
if((p->children[j]->f)>(p->children[j+1]->f))
{
NodeState*temp=p->children[j];
p->children[j]=p->children[j+1];
p->children[j+1]=temp;
}
}
}
}
voidcpyRoad(intdis[],intsrc[],intlen)
{
for(inti=0;idis[i]=src[i];
}
intgetLen(inti,intj,Mapmap)
{
returnimap.rec[i+j*map.num]:
map.rec[j+i*map.num];
}
voidinitNode(NodeState*node,intn)
{
node->road=(int*)malloc(sizeof(int)*n);//分配路径
for(inti=0;inode->road[i]=0;
node->f=node->roadLen=0;
node->cityNum=n;
node->children=(NodeState**)malloc(sizeof(NodeState*)*n-1);//最多的子节点数目
for(inti=0;inode->children[i]=NULL;
}
voidgetNext(introad[],intnextCitys[],intn)
{
intj=0;
for(inti=0;i{
if(!
road[i])//没走过
{
nextCitys[j]=i;
j++;
}
}
}
MapinputMap()
{
Mapmap;
intn=0;
printf("获得距离矩阵,先输入城市数目:
");
scanf("%d",&n);
getchar();
map.num=n;
map.rec=(int*)malloc(sizeof(int)*n*n);//n方
printf("输入数据:
\n");
for(inti=0;ifor(intj=i+1;j{
printf("%c->%c:
",STRING[i],STRING[j]);
scanf("%d",&(map.rec[i+j*n]));
getchar();
}
returnmap;
}
intnearest(introad[],Mapmap)
{
intmin=MAXNUM;
boolflag=false;//判断是否还有没走过节点
for(inti=0;i{
if(!
road[i])//没走过
{
flag=true;
intlen=getLen(0,i,map);//第i个城市到终点距离上层保证i>0
if(lenmin=len;
}
}
if(!
flag)
return0;
returnmin;
}
boolAStar(NodeState&node,Mapmap)
{
//递归出口
if(node.cityNum==map.num)//路径满
{
node.roadLen+=getLen(node.city,0,map);
returnfalse;
}
intl=map.num-node.cityNum;//剩下的城市数
int*nextCitys=(int*)malloc(sizeof(int)*l);
getNext(node.road,nextCitys,map.num);//得到剩下城市名(索引)
//初始化子节点
for(inti=0;i{
node.children[i]=(NodeState*)malloc(sizeof(NodeState));//分配一个子节点内存
initNode(node.children[i],map.num);//初始化子节点
cpyRoad(node.children[i]->road,node.road,map.num);//获得之前走过的路径
node.children[i]->road[nextCitys[i]]=node.cityNum+1;//在路径上加上该子节点
node.children[i]->city=nextCitys[i];
node.children[i]->cityNum=node.cityNum+1;//该节点顺位
node.children[i]->roadLen=node.roadLen+getLen(node.city,node.children[i]->city,map);//新的路径长度
node.children[i]->f=node.children[i]->roadLen+nearest(node.road,map);//计算估价值最后一个节点f值不准
}
//根据估价值排序
sortNode(&node,l);
//向下搜索
booltoFind=true;//是否继续搜索
for(inti=0;i{
if(toFind)//发现结果就不用继续递归了
toFind=AStar(*node.children[i],map);
}
returntoFind;
}
main.cpp
#include"Astar.h"
#include"display.h"
voidmain()
{
//构建地图
Mapm=inputMap();
//初始化头节点
NodeStatehead;
initNode(&head,m.num);
head.city=0;
head.cityNum=1;
head.roadLen=0;
head.road[0]=1;
//开始A*算法
AStar(head,m);
///显示结果
display(head,m.num);
}