将Dijkstra算法修改为A *实现

时间:2012-08-04 17:19:16

标签: c implementation graph-algorithm dijkstra a-star

我正在创建一个穿过迷宫的鼠标的迷宫模拟。 Dijkstra的算法很棒,但是当涉及到猫时,所有这些算法都没有受到特别影响,这就是为什么我试图将我现有的Dijkstra实现修改为A *搜索,使用启发式来避免在整个迷宫中移动的猫。

我在查看一些伪代码时遇到的问题是我不确定哪些结构是等价的,或者我需要介绍什么才能使其工作。任何人都可以向正确的方向提供任何提示或推动吗?

struct path_node *shortestPath(float A[GsizeSqr][GsizeSqr], int xi, int yi, int xf, int yf)
{
    /*
    Solves for the shortest path between grid point (xi,yi) and (xf,yf)
    on the graph encoded by A using Dijkstra's shortest path method.

    The shortest path is returned as a linked list of nodes to be visited.

    Keep track of visited nodes, and the predecessor
    for each node that has been explored while computing the shortest path.*/

    if (xi<0||xi>=Gsize&&yi<0&&yi>=Gsize||xf<0||xf>=Gsize||yf<0||yf>=Gsize)
    {
        fprintf(stderr,"shortestPath(): Endpoint(s) outside of the graph!\n");
        return(NULL);
    }

    int i, j, pCount, findN, row, col, icnt, stNode, finNode, xcnt, ycnt;
    finNode = yf * ceil(sqrt(GsizeSqr)) + xf; //index of start node given its row and col value
    stNode = yi * ceil(sqrt(GsizeSqr)) + xi; //index of finish node given its row and col value

    int p[GsizeSqr]; //predecessors
    int d[GsizeSqr]; //distance from source
    int flags[GsizeSqr]; //(0, 1) for unvisited, visited)

    int g_score[GsizeSqr];
    int f_score[GsizeSqr];

    PriorityQueue Q; //Initialize priority queue that stores (priority, key) values
    Q = init_heap(GsizeSqr);    

    path_node *start; //Maintain a pointer to the starting node
    start = newPathNode(xi, yi);
    start->next = NULL;

    //Initialize p and d with infinity and NULL values (note: -1 means null and 1000000 means inf)
    for(i=0; i < GsizeSqr; i++){
        p[i] = -1;
        d[i] = 10000000;
        flags[i] = 0;
    }

    for(i=0; i < GsizeSqr; i++){
        node in;
        in = create_node(10000000, i);
        enqueue(Q, in);
    }

    //(Note: PQ uses 0 as a sentinel node to make calculating left, right, and parents easier, elements begin at 1)
    decrease_priority(Q, stNode+1, 0); //setting start node in PQ.
    d[stNode] = 0;

    g_score[stNode] = 0;
    //For my heuristic, I'm thinking just using manhattan distances between mouse and cat agents
    f_score[stNode] = g_score[stNode] + heuristic(xi, yi, xf, yf);

    while(Q->heap_size != 1){ //while Q not empty
        node u;
        u = dequeue(Q);
        flags[u.key] = 1;

        //For each adjacent node A[u.key][i]
        for(i=0; i < GsizeSqr; i++){
            if(A[u.key][i] != 0){
                findN = find_node(Q, i);
                if(flags[i] == 0){ //If it is unvisited and new path distance is shorter
                    if(findN != 0 && (d[i] >= A[u.key][i] + d[u.key])){ //reset values and update PQ and mark visited
                        d[i] = A[u.key][i] + d[u.key];
                        p[i] = u.key;                       
                        flags[i] = 1;
                        decrease_priority(Q, findN, d[i]);
                    }
                }
            }
        }
    }

    // Begin selectively filling our LL with values from p[]
    icnt = finNode;
    appendLL(start, xf, yf);
    while(icnt != stNode){
        icnt = p[icnt];
        xcnt = icnt % (int)ceil(sqrt(GsizeSqr));
        ycnt = icnt / (int)ceil(sqrt(GsizeSqr));
        appendLL(start, xcnt, ycnt);
    }

    clean_heap(Q);
    return reverseLL(start);
}

1 个答案:

答案 0 :(得分:1)

您可能已经知道这一点,但A *和Dijkstra算法在最佳优先搜索方面的唯一理论差异是成本函数f(n)。 Dijkstra的算法是f(n) = g(n),而A *是f(n) = g(n) + h(n)。请阅读AIMA了解详情。

就您的代码而言,它目前在g(n) = A[u.key][i] + d[u.key]中存储d[i],因此您需要更改它存储g(n)+ h(n)。您不需要那些新的g_scoref_score变量,只需将启发式添加到该行的末尾并初始化d[stNode]