迷宫遍历打印所有可能的路径C ++

时间:2018-11-17 18:26:05

标签: c++ stack maze

这是我关于堆栈溢出的第一个问题,它是我的作业。我要做的是找到从头到尾的所有可能路径。我正在做的是,如果函数找到'-'并且该函数的参数是'-'所在的索引,则我正在调用该函数。当前参数被压入堆栈。在进一步解释之前,我想显示输出和迷宫。

迷宫

5 6
s - - - - -
- * * * * -
- * * * * - 
- * * * * -
- - - - - e

前两个int是行和列。

输出

00,01,11,21,22,02,03,13,23,22,04,05,15,25,35,45,44,43,42,32,22

从堆栈中取出输出。

在某种程度上,输出是正确的,因为您可以看到该函数遍历每条路径。我无法做的是跟踪功能以及为什么要这样做?因为我要从头开始打印所有路径(本例中为0,0)。当函数有两个要遍历的路径时如何跟踪该函数,以便可以从起始索引中打印出来?

预期产量

00,01,11,21,22
00,01,02,03,13,23,22
00,01,02,03,04,05,15,25,35,45,44,43,42,32,22

如有必要,我还将提供代码。 我已经编辑了代码。我将索引(1,0)推入堆栈,如第一个0到第一个,然后弹出两个,以将其删除。 我了解为什么我的输出是这样的(如上所述),因为,以程序(0,0)中的迷宫为例,它有两个选择up或down。它下降了,因为所有这些语句如果不是,否则函数执行之后的程序会检查其他条件,因此转到正确的其他选项。好的,输出如何?所有索引都被压入堆栈,当找到'e'时,它会打印所有存储的索引,但不会删除它们。对于此示例,我可以在打印后从堆栈中弹出所有内容,并且输出将正常(不重复) 再举一个例子

示例

6 6 s 1 1 1 1 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 1 1 e

在此示例中,您可以看到它在(0,2)有两个选项,因此到达第一个路径末尾后,我无法从此处弹出堆栈中的所有内容。因为它也会弹出(0,0)和(0,1)。我想要的只是弹出直到(0,2)

这就是我想要做的。

#include<iostream>
#include<string.h>
#include<fstream>
using namespace std;
ofstream fout("Q1(output).txt");
ifstream fin("Q1.txt");
class stack
{
    private:
        int row,col;
        int top;
        string str;
        int sourceA,sourceB,destinationA,destinationB;
        char **store;//arr which has maze is passed into class . 'store' has maze.
    public: 
            stack(int row,int col)//constructor , paramerters are rows and cols
        {

            this->row=row;
            this->col=col;
            top=-1;
            sourceA=0;
            sourceB=0;
        }   
    void finish()
    {
        while(top!=-1)
        {
            top--;
        }
    }

    void push(int dataA,int dataB )//push two indexes in str like (0,1) pushed as first 0 then 1 
    {
        if(top==-1)
        {
        top++;
        str[top]=dataA ;
        top++;
        str[top]=dataB  ;
        }
        else
        {
        top++;
        str[top]='1';
        top++;
        str[top]=dataA ;
        top++;
        str[top]=dataB  ;

        }

    }
    void  pop(int varA ,int varB)//This function was made for other purpose but not used 
    {
        for(int a=0;a<top+1;a++)
        {
            if(a==varA && a+1==varB )
            {
                top=a-2;
                cout<<top;
            }
        }

        cout<<endl;
    }
    int ret()
    {
        return top;
    }
    void empty()
    {
        if(top==-1)
        cout<<"\nEmpty\n";
        else 
        cout<<"\nNot Empty\n";
    }
    void get(char **arr)// saving arr(Maze) into store
    {
            char ch;
            store=NULL;
            store=new char*[row];
            for(int a=0;a<row;a++)
            {
                store[a]=new char[col];
                for(int b=0;b<col;b++)
                {

                store[a][b]=arr[a][b];  
                cout<<store[a][b];

                if(arr[a][b]=='s')
                {
                    sourceA=a;//saving the 's' index , my inititate starts from here .
                    sourceB=b;

                }
                else if(arr[a][b]=='e')
                {
                    destinationA=a;//saving the 'e' index , used later.
                    destinationB=b; 
                }
                }
                cout<<endl;         
            }
            }
            int getA()
            {
                return sourceA;
            }
            int getB()
            {
                return sourceB;
            }
            int getAD()
            {
                return destinationA;
            }
            int getBD()
            {
                return destinationB;
            }

            int initiate(int a,int b)
            {
                 int tempA,tempB;
                push(a,b);

                 if(a>0 )
                {

                 if(store[a-1][b]=='1'&&store[a-1][b]!='v')
                {

                    store[a][b]='v';
                    initiate(a-1,b);
                    store[a][b]='1' ;

                }
                }

                 if(b>0 )
                {

                 if(store[a][b-1]=='1'&&store[a][b-1]!='v')
                {

                    store[a][b]='v';
                    initiate(a,b-1);
                    store[a][b]='1' ;


                }
                }

                if(a!=row-1)
                {

                 if(store[a+1][b]=='1'&&store[a+1][b]!='v')
                {

                    store[a][b]='v';
                    initiate(a+1,b);
                    store[a][b]='1' ;

                }
                }

                if(b!=col-1)
                {

                 if(store[a][b+1]=='1'&&store[a][b+1]!='v')
                {

                    store[a][b]='v';                
                    initiate(a,b+1);
                    store[a][b]='1' ;

                }
                }
                 if(a+1==destinationA && b==destinationB ||a-1==destinationA && b==destinationB ||a==destinationA && b+1==destinationB ||a==destinationA && b-1==destinationB )
                {
                    push(destinationA,destinationB);                
                    cout<<"\nPath  : \n";
                    print1();


                }
            pop();

            }
            void print1()
            {
                for(int  a=0;a<top+1;a++)
                {

                    if(str[a]!='1')
                    {
                    int ret=str[a];
                    cout<<ret;
                    fout<<ret;
                    }
                    else
                    {
                        cout<<endl;
                        fout<<endl;                             
                    }
                }

                fout.close();
                }
    int pop()
    {

        int ret=str[top];
        top--;
        int ret1=str[top];
        top--;

    }   
        void show()
        {
            cout<<endl<<endl;
            for(int a=0;a<row;a++)
                {
            for(int b=0;b<col;b++)
                {
                    cout<<store[a][b];

                }
                cout<<endl;
        }
        }

};
main()
{

    char ch;
    int row,col;
    fin >> row;
    fin >> col;
    stack s(row,col);
    char **arr=NULL;
    arr=new char*[row];     
            for(int a=0;a<row;a++)
            {
            arr[a]=new char[col];       
            for(int b=0;b<col;b++)
                {
                fin>>ch;
                arr[a][b]=ch;           
                }

            }

    fin.close();
    s.get(arr);
    s.initiate(s.getA(),s.getB());

    s.show();

    exit(1);
    }

1 个答案:

答案 0 :(得分:0)

可以使用递归来打印所有路径,但是您需要跟踪达到目标所用的路径,并在每次到达目的地时将其打印或保存在其中一个容器。我更喜欢后一种方法。该路径可以是支持推入/弹出操作的堆栈或其他结构。您遍历中访问的每个节点都应添加到路径中,并在其所有邻居都完全扩展后弹出。

这是伪代码中的递归路径构建算法:

function DFS(row: int, col: int, maze: char[][], path: int[][], result: int[][][]) {
    path.push([row, col])

    if ([row, col] is the destination) {
        result.add(path)
    }
    else {
        for (direction in each_cardinal_direction) {
            new_row = row + direction.row
            new_col = col + direction.col

            if (in_bounds(new_row) and in_bounds(new_col) and 
                maze[new_row][new_col] is unvisited) {

                maze[row][col] = visited
                DFS(new_row, new_col, maze, path, result)
                maze[row][col] = unvisited
            }
        }
    }

    path.pop()
}

我尚不完全清楚为什么同时使用显式和隐式状态。通常,在运行DFS时,请使用显式堆栈和while循环,或使用递归并将所有状态作为帧存储在调用堆栈中。考虑提高命名的清晰度,设计和间距/缩进,以便您的逻辑更易于遵循。

例如,str是一个充当堆栈的数组,应这样命名,而您的stack类实际上根本不是堆栈,而是迷宫求解器。您的pop函数不准确,一次只能删除一个元素。

此外,由于您使用的是C ++类和字符串,因此也可以利用容器。

这是一个递归示例,该示例临时修改了迷宫,添加了墙壁以标记访问的节点,从而避免了循环:

#include <iostream>
#include <vector>

void DFS(
    int row, int col,
    std::vector<std::vector<char>> &maze, 
    std::vector<std::pair<int, int>> &path,
    std::vector<std::vector<std::pair<int, int>>> &result
) {
    path.push_back(std::make_pair(row, col));

    if (maze[row][col] == 'e') {
        result.push_back(path);
    }
    else {
        int dirs[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};

        for (auto d : dirs) {
            int r = d[0] + row;
            int c = d[1] + col;

            if (r >= 0 && c >= 0 && r < maze.size() && 
                c < maze[r].size() && maze[r][c] != '*') {
                maze[row][col] = '*';
                DFS(r, c, maze, path, result);
                maze[row][col] = '-';
            }
        }
    }

    path.pop_back();
}

std::vector<std::vector<std::pair<int, int>>> 
getPaths(std::vector<std::vector<char>> maze) {
    std::vector<std::vector<std::pair<int, int>>> result;
    std::vector<std::pair<int, int>> path;
    int row = -1;
    int col = -1;

    for (int i = 0; i < maze.size() && row == -1; i++) {
        for (int j = 0; j < maze[i].size() && col == -1; j++) {
            if (maze[i][j] == 's') {
                row = i;
                col = j;
            }
        }
    }

    DFS(row, col, maze, path, result);
    return result;
}

int main() {
    std::string raw = "s-----\n*-*-*-\n*-e-*-\n**-**-\n**----";
    std::vector<std::vector<char>> maze;
    std::vector<char> row;

    for (int i = 0; i < raw.size(); i++) {
        if (raw[i] == '\n') {
            maze.push_back(row);
            row.clear();
        }
        else {
            row.push_back(raw[i]);
        }
    }

    maze.push_back(row);

    for (auto &path : getPaths(maze)) {
        std::cout << std::endl << '[';

        for (auto &cell : path) {
            std::cout << '(' << cell.first << 
                      "," << cell.second << ')';
        }

        std::cout << ']' << std::endl;
    }
}

输出:

[(0,0)(0,1)(0,2)(0,3)(0,4)(0,5)(1,5)(2,5)(3,5)(4,5)(4,4)(4,3)(4,2)(3,2)(2,2)]
[(0,0)(0,1)(0,2)(0,3)(1,3)(2,3)(2,2)]
[(0,0)(0,1)(1,1)(2,1)(2,2)]

Try it!