启发式算法-A*算法

来源:互联网 发布:we淘宝官方旗舰店 编辑:程序博客网 时间:2024/06/06 21:03

A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法
A算法公式表示为: f(n)=g(n)+h(n)
其中

  • f(n) 是从初始点经由节点n到目标点的估价函数
  • g(n) 是在状态空间中从初始节点到n节点的实际代价
  • h(n) 是从n到目标节点最佳路径的估计代价

启发信息给得越多(估价函数值越大),则A算法需要搜索处理的状态数就越少,效率就越高。但并不是估计值越大越好,有时估价函数值太大会使A算法不一定搜索到最优解。

此时可引入A*算法公式:f*(n) = g* (n) + h* (n)
其中

  • g* (n)是从初始结点到n结点的最短路径代价
  • h* (n)是从n结点到目的结点的最佳路径代价

当我们要求估价函数f(n)中的h(n)都小于等于h*(n)即: h(n) <=h*(n)时 A搜索算法就成为A*搜索算法,所得路径为最优路径。

如某一问题有解,那么利用A*搜索算法对该问题进行搜索则一定能搜索到解,并且一定能搜索到最优的解而结束!

A*例题

问题分析:从节点A开始搜索至#节点,该节点对应的h* (n)即为该城市到目标城市的直线距离(即最佳路径代价),从A点到#节点走过的实际距离(即最短路径代价)则为g* (n)。每次搜索节点查找最小的g* (n) + h* (n)。

#include<stdio.h>#include<stdio.h>#include<stdlib.h>#include<string>int city_num=0;//城市数目int g[100][100];//存储城市间实际距离的邻接矩阵int closeNum=0;//close表大小int track[100];//行驶路径int tra_num=0;//途径城市的数目typedef struct node//代表城市的结构体  { int data; //城市名    int num;//估价函数值     struct node *next; //存储下一个结点的地址     int fa;//上一个城市  }LinkList;typedef struct distance  {       char city;      int dist;  }dis;//存储实际距离和数字与城市名的对应关系dis h[100];LinkList *head,*p,*q;void INITLIST(LinkList *L){ // L=(LinkList*)malloc(sizeof(LinkList));  //判断是否申请成功  if(!L){     printf("无内存空间可分配");exit(0);}  L->next=NULL;} //INITLIST      LinkList close[100];//close表void Init()//初始化,主要是将文件中的内容读入{    FILE *stream=fopen("text.txt","r");    int initNum=0;//城市数目    if(stream==NULL)    printf("The file fscanf.out was not opened\n");    else    {        while(fscanf(stream,"%d%c",&h[initNum].dist,&h[initNum].city) !=EOF){//h数组存储各城市到达目标城市的直线距离            initNum++;        }        city_num=initNum;     fclose(stream);    }    FILE *stream2=fopen("map.txt","r");    //int initNum=0;    if(stream2==NULL)    printf("The file fscanf.out was not opened\n");    else    {        for(int i=0;i<initNum;i++){            for(int j=0;j<initNum;j++){                if(fscanf(stream,"%d",&g[i][j]) !=EOF)                    //initNum++;                        continue;            }        }     fclose(stream);    }}int Initend()//仅仅是为了找到目标城市而已{    for(int i=0;i<city_num;i++){        if(h[i].dist==0)            return i;    }    return -1;}int find(char c){    for(int i=0;i<city_num;i++){        if(h[i].city==c)            return i;    }    return -1;}void addOpen(LinkList *p,int a,int dis,int f)//将走过的节点加入到open表{    LinkList *q;    //p =(LinkList *)malloc(sizeof(LinkList));//  q =(LinkList *)malloc(sizeof(LinkList));    q=head;    p->data=a;    p->fa=f;    p->num=dis+h[a].dist;    while(1){        if(q->next==NULL||q->next->num>p->num){            p->next=q->next;            q->next=p;            return;        }        q=q->next;    }}void deleteOpen(int n)//将重新找到更短的路径从open表替换{    LinkList *r;    r=head;    while(r->next!=NULL){        if(r->next->data==n){            r->next=r->next->next;            return;        }        else        {            r=r->next;        }    }    return;}int findClose(int a)//查找某城市是否在close表中{    for(int i=0;i<city_num;i++){        if(close[i].data==a)            return i;    }    return -1;}void deleteclose(int n)//在需要时从close表中转移出来{    for(int i=0;i<closeNum;i++){        if(close[i].data==n){            close[i].data=close[closeNum-1].data;            close[i].num=close[closeNum-1].num;            closeNum--;            return;        }    }    return;}int findOpen(int n,int dis)//查找某节点是否在open表中{    LinkList *r;    r=head;    int i=0;    while(r->next!=NULL){        if(r->next->data==n){            if(r->next->num>dis+h[n].dist)                return 1;            else                return 0;        }           else        {            r=r->next;            i++;        }    }    return -1;}void Track()//形成track表{    int a,b;    track[tra_num++]=head->next->data;    b=head->next->fa;    track[tra_num++]=b;    while(1){        for(int i=0;i<closeNum;i++){            if(close[i].data==b){                if(close[i].fa==-1)                    return;                b=close[i].fa;                track[tra_num++]=b;                break;            }        }    }}int main(){    Init();    char name;    int end;    printf("输入初始城市:");    scanf("%c",&name);    end=Initend();//找到目标城市    head =(LinkList *)malloc(sizeof(LinkList));    INITLIST(head);//初始化open表    p =(LinkList *)malloc(sizeof(LinkList));//...    p->next=head->next;    head->next=p;    p->num=h[find(name)].dist;    p->data=find(name);    p->fa=-1;//...起点城市入open表    LinkList *t;    while(head->next->data!=end){        t=head->next;        //addTrack(t);        head->next=t->next;//open表头入closeclose[closeNum].data=t->data;        close[closeNum].num=t->num;        close[closeNum++].fa=t->fa;        //printf("%d\n",t->data);        for(int i=0;i<city_num;i++){            if(g[t->data][i]!=0){//如果找到与此城市相连的城市&&不在close表中                p =(LinkList *)malloc(sizeof(LinkList));                if(findClose(i)==-1&&findOpen(i,t->num-h[t->data].dist+g[t->data][i])==-1){                    addOpen(p,i,t->num-h[t->data].dist+g[t->data][i],t->data);//添加到open表中(城市序号,到此城市要走的路)                }                if(findOpen(i,t->num-h[t->data].dist+g[t->data][i])==1){                    deleteOpen(i);                    addOpen(p,i,t->num-h[t->data].dist+g[t->data][i],t->data);                }                if(findClose(i)!=-1){                    if(close[findClose(i)].num>t->num-h[t->data].dist+g[t->data][i]+h[t->data].dist){                        deleteclose(i);                        addOpen(p,i,t->num-h[t->data].dist+g[t->data][i],t->data);                    }                }            }    //      close[closeNum].data=t->data;    //      close[closeNum].next=NULL;    //      close[closeNum].num=t->num;    //      closeNum++;        }    }    Track();    printf("最优路径为:");    for(int i=tra_num-1;i>=0;i--){        printf("%c  ",h[track[i]].city);    }    printf("\n");    return 0;}

结果截图

0 0
原创粉丝点击