迷宫求解器复杂度

Posted

技术标签:

【中文标题】迷宫求解器复杂度【英文标题】:Maze solver complexity 【发布时间】:2013-11-25 11:53:31 【问题描述】:

我有几个关于迷宫的问题 - 求解器算法:C

    递归(回溯)迷宫求解器的时间复杂度是多少?(作为矩阵中路径的数量?-我无法计算出这个数字..) 基于 BFS 的迷宫求解器的时间复杂度是多少?(O(n^2)?)n 是平方迷宫矩阵的维数? 计算迷宫中从源到目的地的所有可能路径的数量的最佳算法是什么? 您能否提出这个想法是否以及如何使用并行计算 (opecl/cuda) 来实现?

这是我的迷宫求解器的类,它具有基于暴力(递归)和 bfs 的版本。我实现了它,问题基于这个迷宫求解器实现



//MazeSolver.h
//#define N 5

    typedef enum BLACK,WHITE,GRAY,VISITED color;
    class MazeSolver
    
    public:
        MazeSolver()
        struct Cell
        
            unsigned int _x;
            unsigned int _y;
            Cell* _p;
            Cell(unsigned int x = 0,unsigned int y = 0, Cell* p = NULL) : _x(x),_y(y),_p(p) 
            bool operator == (const Cell& c)
            
                return _x == c._x && _y == c._y;
            
        ;
         bool solveMazeBrute(color maze[][N],unsigned int n,int xS,int yS,int xD,int yD,std::list<Cell>& path);
         bool solveMazeBFS(color maze[][N],unsigned int n,int xS,int yS,int xD,int yD,std::list<Cell>& path);
    private:
        std::queue<Cell* > _bfs;
        std::vector<Cell* > _cells;

        Cell* addCellBFS(color maze[][N],unsigned int n,int x,int y,Cell* p = NULL);
    ;

    //MazeSolver.cpp
    MazeSolver::Cell*  MazeSolver::addCellBFS(color maze[][N],unsigned int n,int x,int y,Cell* p)
    
        if (x >= 0 && x < n && y >= 0 && y < n && maze[x][y] == WHITE)
        
            Cell* c = new Cell(x,y,p);
            maze [x][y] = VISITED;

            _bfs.push(c);
            _cells.push_back(c);
            return c;
        
        return NULL;
    

    bool MazeSolver::solveMazeBrute(color maze[][N],unsigned int n,int xS,int yS,int xD,int yD,std::list<MazeSolver::Cell>& path)
    
        bool solved = false;
        if (xS < 0 || xS >= n || yS < 0 || yS >= n || maze[xS][yS] == VISITED || maze[xS][yS] == BLACK)
        
            return false;
        

        Cell s(xS,yS);
        Cell d(xD,yD);

        if (s == d)
        
            path.push_front(s);
            return true;
        
        maze[xS][yS] = VISITED;
        if (solveMazeBrute(maze,n,xS + 1,yS,xD,yD,path) || 
            solveMazeBrute(maze,n,xS - 1,yS,xD,yD,path) ||
            solveMazeBrute(maze,n,xS,yS  + 1,xD,yD,path) ||
            solveMazeBrute(maze,n,xS,yS - 1,xD,yD,path))
        
            path.push_front(s);
            solved = true;
        
        maze[xS][yS] = WHITE;
        return solved;
    

    bool MazeSolver::solveMazeBFS(color maze[][N],unsigned int n,int xS,int yS,int xD,int yD,std::list<Cell>& path)
    
        Cell d(xD,yD); 
        addCellBFS(maze,n,xS,yS);
        while(!_bfs.empty())
        
            Cell* cur = _bfs.front();
            if (*cur == d)
            
                while (cur != NULL)
                
                    path.push_front(*cur);
                    cur = cur->_p;
                
                return true;
            
            _bfs.pop();
            addCellBFS(maze,n,cur->_x - 1,cur->_y,cur);
            addCellBFS(maze,n,cur->_x + 1,cur->_y,cur);
            addCellBFS(maze,n,cur->_x,cur->_y - 1,cur);
            addCellBFS(maze,n,cur->_x,cur->_y + 1,cur);
        
        for(std::vector<Cell*>::iterator itC= _cells.begin();itC != _cells.end();++itC)
        
              maze[(*itC)->_x][(*itC)->_y] = WHITE;
            delete *itC;
        
        return false;
    

【问题讨论】:

代码与您的问题有何关联? @AbhishekBansal - 这是我的迷宫求解器的一个类,它具有粗暴(递归)和基于 bfs 的版本。我实现了它,问题基于这个迷宫求解器实现 “最佳算法”用于所有可能的无循环路径的数量,或所有最短路径的数量? AFAIR,前者未知,因为任务是NP-Hard,但我不确定。后者是修改后的 SSSP 算法,对于具有未加权边的图,其运行时间为 O(|E|),在这种情况下等于 O(numberOfCells)。 @comonad - 谢谢!您如何看待递归解决方案的复杂性? 你的意思是solveMazeBrute?那是指数级的。取 2x3 矩阵:键盘上的“qweasd”。 e 是黑色的。 d 是目的地。 s 是开始。您按照上/下/左/右的顺序行走。因为您将访问的单元格重新绘制为白色,您将再次访问它们,直到您碰巧访问了 d。让大写表示绘制白色,小写表示访问,则事件为:“swqaAQW(s)aqwWQA(s)dDS”。 (如您所见,您只需要两种颜色:allowedtovisit + donotgothere。在搜索路径时不要使用 allowedtovisit 重新绘制 donotgothere。最坏情况下的运行时间将为 O(|allowedtovisitCells|)。) 【参考方案1】:

也许我们可以在 O(n) 内找到目标。

让我们想象一下 5X5 矩阵。 在每次迭代中,我们将向前迈出一步,我们将检查单元格是否有效并且不是迷宫的尽头,并将其标记为“已访问”。

所以,我们将从第一个单元格 (0,0) 开始。在下一次迭代中,我们将检查下一层,意思是 (0,1),(1,0),在下一次迭代中,我们将继续检查下一层 (0,2),(1,1),(2, 0)。等等。

所以,我们将只检查每个单元格一次!我们会在 n 复杂度中找到终点(目标)。

我错了吗?

【讨论】:

我假设你的意思是 O(k),其中 k=n² 并且迷宫是一个 nxn 矩阵。 @MeNa - 是的。我就是这么想的。谢谢

以上是关于迷宫求解器复杂度的主要内容,如果未能解决你的问题,请参考以下文章

迷宫问题的求解(广度优先搜索)

宽度优先搜索BFS,求解迷宫问题

迷宫问题求解利用栈与递归求解出口

利用栈实现迷宫求解

迷宫求解程序的回溯逻辑错误

迷宫问题(MazePath)的求解——利用回溯法(backtracking)