A*算法的原理和实现

一:A*的介绍

A*算法是一种启发式搜索算法,就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无畏的搜索路径,提到了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。

该算法可以用公式f(n)=g(n)+h(n)表示,其中 f(n) 是从初始点经由节点n到目标点的估价函数,g(n) 是在状态空间中从初始节点到n节点的实际代价,h(n) 是从n到目标节点最佳路径的估计代价。h*(n)是从n到目标节点最佳路径的实际代价,那么整个个启发式搜索过程必须保证h(n)<=h*(n),否则搜索出错。

对于h(n) 的选择,越接近h*(n)则速度越快。

主要有以下几种启发函数

曼哈顿距离:

定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里德空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。例如在平面上,坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的曼哈顿距离为:|x1 - x2| + |y1 - y2|。

欧氏距离:

是一个通常采用的距离定义,它是在m维空间中两个点之间的真实距离。在二维和三维空间中的欧氏距离的就是两点之间的距离。例如在平面上,坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的欧氏距离为: sqrt((x1-x2)^2+(y1-y2)^2 )。

切比雪夫距离:

是两个向量之间各分量差值的最大值。例如在平面上,坐标(x1, y1)的点P1与坐标(x2, y2)的点P2的切比雪夫距离为:max(|x1 - x2| , |y1 - y2|)。

二:A*算法的过程

目标:要从A走到P,节点后的是估值

搜索过程中设置两个表:OPEN和CLOSED。OPEN表保存了所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。算法中有一步是根据估价函数重排OPEN表。这样循环中的每一步只考虑OPEN表中状态最好的节点。具体搜索过程如下:

1)初始状态:                

 OPEN=[A5];CLOSED=[];

2)估算A5,取得搜有子节点,并放入OPEN表中;

 OPEN=[B4,C4,D6];CLOSED=[A5]

3)估算B4,取得搜有子节点,并放入OPEN表中;

 OPEN=[C4,E5,F5,D6];CLOSED=[B4,A5]

4)估算C4;取得搜有子节点,并放入OPEN表中;

 OPEN=[H3,G4,E5,F5,D6];CLOSED=[C4,B4,A5]

5)估算H3,取得搜有子节点,并放入OPEN表中;

 OPEN=[O2,P3,G4,E5,F5,D6];CLOSED=[H3,C4,B4,A5]

6)估算O2,取得搜有子节点,并放入OPEN表中;

 OPEN=[P3,G4,E5,F5,D6];CLOSED=[O2,H3,C4,B4,A5]

7)估算P3,已得到解;

其中,OPEN表可以用优先队列实现

代码:

POJ2243

在棋盘上,骑士走“日”的形态,求从棋盘一点到另外一点的最短步数?

#include<stdio.h>
#include<queue>
#include<string.h>
#include<math.h>
using namespace std;
int a[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}},vist[9][9];
struct node
{
    int x,y,step;
    int f,g,h;
    bool operator < (const node &anOther) const {
        return f > anOther.f;
    }
};
node s,e;  

int find_h(node tmp){
  double a;
		a=((e.x-tmp.x)^2+(e.y-tmp.y)^2);
		int b=sqrt(a);
		return b*10;
}
priority_queue<node>que;  

int AStar(node start,node end)
{
    int i;
    node cur,next;
    while( !que.empty() ) que.pop();
    que.push(start);
    while( !que.empty() )
    {
        cur = que.top();
        que.pop();
        for(i=0;i<8;i++)
        {
            next.x = cur.x + a[i][0];
            next.y = cur.y + a[i][1];
            if( !vist[next.x][next.y] && next.x>=1 && next.x<=8 && next.y>=1 && next.y<=8 )
            {
                vist[ next.x ][ next.y ] = 1;
                next.step = cur.step + 1;
                next.g = cur.g +23;
                next.h = find_h(next);
                next.f = next.g + next.h;  

                if(next.x == end.x && next.y == end.y )
                    return next.step;
                que.push(next);
            }
        }
    }
    return 0;
}  

int main()
{
    int move;
    char t,m;
    while( scanf("%c%d %c%d",&t,&s.y,&m,&e.y) !=EOF)
    {
        getchar();
        memset(vist,0,sizeof(vist));
        move = 0;
        s.x = t - 'a' + 1;
        e.x = m - 'a' + 1;
        s.step = 0;
        s.g = 0;
        s.f = s.g + find_h(s);
        vist[s.x][s.y]=1;
        move = AStar(s,e);
        printf("To get from %c%d to %c%d takes %d knight moves.\n",t,s.y,m,e.y,move);
    }
    return 0;
}  
时间: 2024-10-14 06:30:15

A*算法的原理和实现的相关文章

机器学习笔记_PRML_Adaboost 算法的原理与推导

转自:http://blog.csdn.net/v_july_v/article/details/40718799 Adaboost 算法的原理与推导 1 Adaboost的原理 1.1 Adaboost是什么 AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出.它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器.同时,在每一轮中加

《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果

本文完全转载:http://www.cnblogs.com/Imageshop/p/3281703.html,再次仅当学习交流使用.. <Single Image Haze Removal Using Dark Channel Prior>一文中图像去雾算法的原理.实现.效果(速度可实时) 本文算法合作联系QQ: 33184777, 非诚勿扰 邮件地址:   [email protected] 最新的效果见 :http://video.sina.com.cn/v/b/124538950-125

常见hash算法的原理(转)

常见hash算法的原理 散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. 比如我们存储70个元素,但我们可能为这70个元素申请了100个元素的空间.7

一个日期算法的原理分析

1.问题描述 在 OSC 问答频道有一个问题:时间算法:帮忙解答下 简单的复述一遍就是能够通过如下式子来计算month月day日是一年的第几天. 闰年是 day_of_year=(275*month)/9 - (month+9)/12 + day - 30 非闰年比这个少1天.可以简单的验证,这个式子中每个部分计算后都取整,整个结果总是对的. 我们知道1.3.5.7.8.10.12都是31天,2月的天数有点诡异,其他都是30天,正常情况下我们写程序会写很多if来判断月份,进而计算累积的天数.但是

理解RMQ问题和ST算法的原理

下图为TI C6xx DSP Nyquist总线拓扑图,总线连接了master与slave,提供了高速的数据传输.有很多种速率不同的总线,如图中的红色方框,最高速总线为CPU/2 TeraNet SCR(即VBUSM SCR),带宽为256bit,其他低速总线为CPU/3,CPU/6,带宽参考图中所示.总线之间用Bridge(桥)连接,作用包括转换总线的速率,使之与所流向总线的速率相同等. 在具体应用中,各种速率的总线完全可以满足复杂的数据传输,而数据传输的瓶颈往往在于连接总线之间的Bridge

常见hash算法的原理

转自:http://blog.csdn.net/zxycode007/article/details/6999984 散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的

英文分词的算法和原理

英文分词的算法和原理 根据文档相关性计算公式 TF-IDF:http://lutaf.com/210.htm BM25:http://lutaf.com/211.htm 分词质量对于基于词频的相关性计算是无比重要的 英文(西方语言)语言的基本单位就是单词,所以分词特别容易做,只需要3步: 根据空格/符号/段落 分隔,得到单词组 过滤,排除掉stop word 提取词干 第一步:按空格/符号分词 用正则表达式很容易 pattern = r'''(?x)    # set flag to allow

3、贪心算法的原理与设计

贪心算法的原理与设计 贪心算法的设计步骤 1.将最优化问题转化为这样的形式:对其做出一次选择后,只剩下一个子问题要求解. 这个问题可以引用前面得到的活动选择问题进行说明 ,如在活动选择问题中,设Aij 代表的是活动ai?  结束后开始,且在aj结束之前进的一个子问题,于是 Aij=Aik+ak+Akj                      于我们将区间[i,j]活动的安排就变成了两个子区间[i,k]和[k,j]的优化问题,这问题进行了变化. 但是如果我们如果采用贪心策略,先对活动的结束时间进

Floyd算法的原理和实现

一.算法介绍 Floyd算法是一种在有向图中求最短路径的算法.相比不能再有向图中包含负权值的dijkstra算法,Floyd算法可以用在拥有负权值的有向图中求解最短路径(不过不能包含负权回路).它是一种求解有向图中点与点之间最短路径的算法. 我们检查有向图中的每一个节点X,对于图中过的2点A和B,如果有Dis(AX)+Dis(XB)<Dis(AB),那么使得Dis(AB)=Dis(AX)+Dis(XB).当所有的节点X遍历完后,AB的最短路径就求出来了. 所以,核心代码很简单,其中N是顶点个数,

Adaboost 算法的原理与推导——转载及修改完善

<Adaboost算法的原理与推导>一文为他人所写,原文链接: http://blog.csdn.net/v_july_v/article/details/40718799 另外此文大部分是摘录李航的<统计学笔记>一书,原书下载链接:http://vdisk.weibo.com/s/z4UjMcqGpoNTw?from=page_100505_profile&wvr=6 在根据文中推导是发现有计算错误以及省略的步骤,在下文将会进行说明. ------------------