【问题标题】:Shortest Path, No Left Turns, Printing Path最短路径,无左转,打印路径
【发布时间】:2011-12-10 21:56:10
【问题描述】:

我正在做一个项目,我需要找到从单一来源到单一目的地的最短路径。我只能右转,所以有时我需要右转三个而不是左转。我已经把算法搞定了(我想),但是我在打印之后的路径时遇到了问题。我在每个图块上都保留了一个来自指针,但是当我从最后开始并遵循来自指针时,获取三个权限的时间会导致一个循环,因为来自指针被新的指针覆盖.如何识别这种循环模式并回到正轨以打印完整路径?

这是我的 backTracker 类

class backTracker {
    int rows;
    int cols;
    tile** map;
    tile* start;
    tile* end;
    int rightTurns;
    int loopTracker;
    bool done;
    int** visits;
    MyStack visited;
    public:
    backTracker(int inRows, int inCols, tile** inMap, tile* inStart,
                                                tile* inEnd, int** &inVisits) {
            rows = inRows;
            cols = inCols;
            map = inMap;
            start = inStart;
            end = inEnd;
            rightTurns = 0;
            loopTracker = 0;
            done = false;
            visits = inVisits;
    }
    void findPath() {
        backTrack(start);
    }
    private:
    void backTrack(tile* currTile) {
        if (currTile == end || done) {
            cout << "end found" << endl;
            done = true;
            return;
        }
        else if (promising(currTile)) {
            //if it's the start tile, check all directions
            if (currTile->cameFrom == 0) {
                tile* next;
                int cRow = currTile->row;
                int cCol = currTile->col;
                if (cRow != 0) {
                    next = &map[cRow-1][cCol];
                    next->cameFrom = currTile;
                    next->directionFrom = 'N';
                    backTrack(next);
                }
                if (cRow != rows - 1) {
                    next = &map[cRow+1][cCol];
                    next->cameFrom = currTile;
                    next->directionFrom = 'S';
                    backTrack(next);
                }
                if (cCol != cols - 1) {
                    next = &map[cRow][cCol+1];
                    next->cameFrom = currTile;
                    next->directionFrom = 'E';
                    backTrack(next);
                }
                if (cCol != 0) {
                    next = &map[cRow][cCol-1];
                    next->cameFrom = currTile;
                    next->directionFrom = 'W';
                    backTrack(next);
                }
            }
            //otherwise check straight and right
            else {
                    currTile->straight = 0; //the tile in the straight direction
                    currTile->right = 0;//the tile to the right of the straight tile
                    //easier to read
                    int row = currTile->row;
                    int col = currTile->col;
                    bool good = false;
                    //find the straight and right tiles depending on current
                    //direction, also check if the tile has been visited from
                    //that direction already
                    if (currTile->directionFrom == 'N') {
                        if (col != cols - 1) {
                            if (map[row][col+1].directionFrom != 'E') {
                                currTile->right = &map[row][col+1];
                                currTile->right->directionFrom = 'E';
                                good = true;
                                tile* right = currTile->right;
                                right->cameFrom = currTile;
                                backTrack(right);
                            }
                        }
                        if (row != 0) {
                            //if it hasn't already been visited from this direction
                            if (map[row-1][col].directionFrom != 'N') {
                                currTile->straight = &map[row-1][col];
                                good = true;
                                tile* str = currTile->straight;
                                str->cameFrom = currTile;
                                //going straight so direction is the same
                                str->directionFrom = currTile->directionFrom;
                                backTrack(str);
                            }
                        }
                    }
                    else if (currTile->directionFrom == 'W') {
                        if (row != 0) {
                            if (map[row-1][col].directionFrom != 'N') {
                                currTile->right = &map[row-1][col];
                                currTile->right->directionFrom = 'N';
                                good = true;
                                tile* right = currTile->right;
                                right->cameFrom = currTile;
                                backTrack(right);
                            }
                        }
                        if (col != 0) {
                            if (map[row][col-1].directionFrom != 'W') {
                                currTile->straight = &map[row][col-1];
                                good = true;
                                tile* str = currTile->straight;
                                str->cameFrom = currTile;
                                //going straight so direction is the same
                                str->directionFrom = currTile->directionFrom;
                                backTrack(str);
                            }
                        }
                    }
                    else if (currTile->directionFrom == 'S') {
                        if (col != 0) {
                            if (map[row][col-1].directionFrom != 'W') {
                                currTile->right = &map[row][col-1];
                                currTile->right->directionFrom = 'W';
                                good = true;
                                tile* right = currTile->right;
                                right->cameFrom = currTile;
                                backTrack(right);
                            }
                        }
                            if (row != rows - 1) {
                            if (map[row+1][col].directionFrom != 'S') {
                                currTile->straight = &map[row+1][col];
                                good = true;
                                tile* str = currTile->straight;
                                str->cameFrom = currTile;
                                //going straight so direction is the same
                                str->directionFrom = currTile->directionFrom;
                                backTrack(str);
                            }
                        }
                    }
                    else if (currTile->directionFrom == 'E'){
                        if (row != row - 1) {
                            if (map[row+1][col].directionFrom != 'S') {
                                currTile->right = &map[row+1][col];
                                currTile->right->directionFrom = 'S';
                                good = true;
                                tile* right = currTile->right;
                                right->cameFrom = currTile;
                                backTrack(right);
                            }
                        }
                        if (col != cols - 1) {
                            if (map[row][col+1].directionFrom != 'E') {
                                currTile->straight = &map[row][col+1];
                                good = true;
                                tile* str = currTile->straight;
                                str->cameFrom = currTile;
                                //going straight so direction is the same
                                str->directionFrom = currTile->directionFrom;
                                backTrack(str);
                            }
                        }
                    }

                }

            }

        }
        //checks for walls
        bool promising(tile* currTile) {
            if (currTile->type == WALL) {
                return false;
            }
            else {
                return true;
            }
    }

【问题讨论】:

  • 您能给我们提供任何具体信息吗?一个图像?代码?描述问题的论文?
  • 是上课用的,政策是不在任何地方公开发布代码……我是用回溯算法找路径的,环境就是一个字母网格,'X '成为一堵墙'。作为一个有效的移动空间。抱歉,我无法为您提供更多信息。
  • 我认为您应该只保留一组经过的图块,而不是依赖图块来保存该信息。你不会有任何歧义。
  • 如何区分路径中的图块和仅访问过的图块?
  • 只存储您要到达的图块的坐标。

标签: c++ graph shortest-path


【解决方案1】:

在每个单元格中存储多条(最多四条)信息。我不知道您如何搜索矩阵,但我会使用某种广度优先算法来尝试找到从所有四个方向到每个单元格的路径。每个单元必须存储从所有四个方向到达该单元所必须采取的步数。一旦到达目的地,此路径构建就会停止。要重新创建路径,然后倒退并迭代地找到距当前单元格距离目的地少一步的相邻单元格。

【讨论】:

  • 现在我正在使用回溯算法(项目规范要求),它进行深度优先搜索,只检查正前方和右侧的图块,修剪左侧和向后方向。
  • 我猜同样的推理也适用于深度优先。您需要额外的空间来存储额外的信息,因为每个单元格只有一个信息空间。
  • 除了 comeFrom 之外,还有哪些类型的信息有助于存储?
  • 您需要为每个单元格设置一个堆栈,其值为 comeFrom1、 comeFrom2、 comeFrom3。当您访问一个单元格时,您会发现下一步要去哪里,然后从堆栈中删除该值。当您下次访问该单元格时,将会有一些其他价值在等着您。我认为最大堆栈大小为 3。
  • 但是等等,如果你做深度优先,那么你已经有了完整的路径。它是在递归期间创建的。细胞不必有任何访问信息。您所需要的只是一些列表或向量,您可以在其中推送下一个单元格,并在回溯时弹出当前单元格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多