码迷,mamicode.com
首页 > 其他好文 > 详细

A star 搜索入门

时间:2014-10-01 22:18:11      阅读:289      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   os   ar   for   sp   div   

终于学习了传说中的A*搜索~...

先通俗的说一下A*搜索的原理,然后用代码实现~

 

A*搜索是在基于广搜的基础上的一种启发式搜索方式(我也不知道启发式是什么意思),可以大大降低搜索时间,找出相对正确的最优路径。

 

这里用到了特殊的存储结构---优先队列,可以优化将查找的复杂度从O(n)有化成O(logn);

1、首先我们从原点开始进行A*搜索,把原点入队列,然后标记为已访问

2.接收优先队列队列第一个元素并pop掉,判断第一个元素相邻的八个位置,如果其中有的位置是障碍物或者超出地图范围或者已经访问过,则排除,其他位置入栈,并用pre指针指向父节点

3.找出其中相对h+g最优的解(可用优先队列实现),重复2步骤,直到找到终点;

 

代码实现

#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;

int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};

struct node
{
    bool visit;
    int x,y;
    double hx,gx;//核心
    char ch;
    node *pre;
    
    node()
    {
        visit = 0;
        pre = NULL; 
    } 
}map[51][51],start,end;


bool judge(int x, int y)
{
    if(x>=0 && x<=50 && y>=0 && y<=50)
        return true;
    else
        return false;
}



double Euclidean_dis(int sx,int sy,int ex,int ey){//欧几里德
    double nn;
    nn=sqrt((sx-ex)*(sx-ex)+(sy-ey)*(sy-ey));
    return nn;
}

double Chebyshev_dis(int sx,int sy,int ex,int ey){//切比雪夫
    double nn;
    nn=max(abs(sx-ex),abs(sy-ey));
    return nn;
}

double jiaquan_Manhattan(int sx,int sy,int ex,int ey){//加权曼哈顿   //better
    double nn,dx,dy;
    dx=abs(sx-ex);
    dy=abs(sy-ey);
    if(dx>dy)
        nn=10*dx+6*dy;
    else
        nn=6*dx+10*dy;
    return nn;
}

//重载运算符 
bool operator<(node a, node b)
{
    return a.gx + a.hx > b.gx + b.hx;
}


//寻找路径 
void viewback()
{
    node *p;
    p = map[end.x][end.y].pre;
    
    while(p)
    {
        if(p->pre)
        {
            p->ch = v;
        }
        p = p->pre;
    }
    return;
}


void Astar()
{
    priority_queue<node> q;
    q.push(start);
    
    int xx,yy;
    int i;
    
    while(!q.empty())
    {
        node now = q.top();
        q.pop();
        
        if(now.x==end.x&&now.y == end.y)
        {
            break;
        }
        
        for(int i=0; i<4; i++)
        {
            xx = now.x + dir[i][0];
            yy = now.y + dir[i][1];
            
            if(!judge(xx, yy)||map[xx][yy].ch == x || map[xx][yy].visit == 1)
            {
                continue;
            }
            
            map[xx][yy].visit = 1;
            map[xx][yy].pre = &map[now.x][now.y];
            
            map[xx][yy].hx = jiaquan_Manhattan(xx, yy, end.x, end.y);
            
            map[xx][yy].gx = now.gx + 1;
            
            q.push(map[xx][yy]);
        }
    }
    return ;
}


int main()
{
    freopen("t.txt", "r", stdin);
    int i,j,visi_num=0;
    for(i=0;i<50;i++){
        for(j=0;j<50;j++){
            cin>>map[i][j].ch;
            map[i][j].x=i;
            map[i][j].y=j;
            if(map[i][j].ch==s){
                map[i][j].gx=0;
                map[i][j].visit=1;

                start=map[i][j];
            }
            if(map[i][j].ch==e)
                end=map[i][j];
        }
        getchar();
    }
    cout<<"结果---------------------------------------------------"<<endl;
    Astar();
    viewback();

    for(i=0;i<50;i++){
        for(j=0;j<50;j++){
            visi_num+=map[i][j].visit;
            if(map[i][j].ch==v || map[i][j].ch==e || map[i][j].ch==s)
                printf("%c",map[i][j].ch);
            else if(map[i][j].visit)
                printf("%d",map[i][j].visit);
            else
                printf("%c",map[i][j].ch);
        }
        cout<<"\n";
    }
    printf("\n遍历节点 %d 个\n",visi_num);
    return 0;
}

 

 

这个代码写的很好,我从网上好不容易找到的~...

A star 搜索入门

标签:style   blog   color   io   os   ar   for   sp   div   

原文地址:http://www.cnblogs.com/ltwy/p/4003466.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!