【问题标题】:why am I getting segmentation fault? I am trying to solve the rat in a maze problem为什么我会出现分段错误?我正在尝试解决迷宫问题中的老鼠
【发布时间】:2021-03-09 15:25:55
【问题描述】:

为什么会出现分段错误?我正在尝试解决迷宫问题中的老鼠。 下面是给我分段错误的代码
可能有一些错误将二维数组传递给函数,但对我来说似乎没问题 我已经在函数 rinm 中应用了基本条件,并从 main() 传递了解矩阵以及用户输入矩阵。

bool rinm(int** maze,int** sol,int n, int x, int y)
{
    if(x==n-1 && y==n-1)
    {
            sol[x][y]=1;

        //print the path
        for (int i = 0; i < n; ++i)
        {
            /* code */
            for (int j = 0; j < n; ++j)
            {
                cout<<sol[i][j]<<" ";

            }

            cout<<endl;
        }
        return true;
    }
    else if(x<0 || y<0 || x>=n || y>=n || maze[x][y]==0)
    {
        return false;
    }
    
    sol[x][y]=1;

    bool up=rinm(maze,sol,n,x-1,y);
    bool down=rinm(maze,sol,n,x+1,y);
    bool right=rinm(maze,sol,n,x,y+1);
    bool left = rinm(maze,sol,n,x,y-1);
   
    sol[x][y]=0;

    if(up||down||right||left)
    {
        return true;
    }
}

这是我的主要功能。

 int main()
    {
        int n;
        cin>>n;
        int** maze=new int*[n];//rows
        for (int i = 0; i < n; ++i)
        {
            maze[i]=new int [n]; // columns
        }
        
        for (int i = 0; i < n; ++i)
        {
            for(int j=0; j<n;j++)
            {
                cin>>maze[i][j];
            }
        }
    
        int** sol=new int*[n];
        for (int i = 0; i < n; ++i)
        {
            sol[i]=new int [n]; // columns
        }
        for (int i = 0; i < n; ++i)
        {
            for(int j=0; j<n;j++)
            {
                sol[i][j]=0;
            }
        }
        bool path=rinm(maze,sol,n,0,0);
        if(path==false)
            cout<<"path doesnot exist\n";
    
        return 0;
    
    }

我哪里错了?

【问题讨论】:

  • 这个循环将无限工作,因为您没有存储任何访问过的状态数组。假设输入是2 1 1 0 1,那么你通过 up 和 down 函数调用不断地重新访问 1
  • 你能指定rat in a maze problem是什么吗?
  • @risingStark 你能详细说明我需要修改什么吗?我已经添加了基本条件以及何时需要返回 false....
  • @risingStark 你能详细说明我需要修改什么吗?我已经添加了基本条件以及何时需要返回 false....
  • 在调试器中运行时会发生什么 - 您可以看到失败的行和变量的值

标签: c++ data-structures segmentation-fault backtracking


【解决方案1】:

问题是不断重新访问相同的单元格,因为您没有检查您是否是第一次访问一个单元格。

例如对于输入:

2
1 1
0 1

我将输入(x, y)的移动序列,你可以看到它会陷入无限循环。

(0, 0) 
    -> (-1, 0) (up function call, returns false since x < 0)
    -> (1, 0) (down function call, return false since maze[1][0] = 0)
    -> (0, 1) 
           -> (-1, 1) (up function call, returns false since x < 0)
           -> (1, 1) (down function call, solution found. Print sol matrix)
           -> (0, 2) (right function call, returns false since y >= 2)
           -> (0, 0) (left function call)

问题就在这里。现在你回到(0, 0) 并且递归继续运行而没有任何终止。这会导致递归堆栈分配大量内存,您会得到 Segmentation Fault

我希望你能理解这里的问题。如果您仍有疑问,只需在进入循环后立即打印(x, y),您就会看到这种情况发生。


这是我对代码所做的更改。

这是更正后的代码。这将打印到达目的地的所有可用路径。
如果sol[x][y] == 1,则该函数返回false,这意味着您之前也访问过单元格(x, y)

bool rinm(int** maze,int** sol,int n, int x, int y)
{
    if(x==n-1 && y==n-1)
    {
            sol[x][y]=1;

        //print the path
        for (int i = 0; i < n; ++i)
        {
            /* code */
            for (int j = 0; j < n; ++j)
            {
                cout<<sol[i][j]<<" ";

            }

            cout<<endl;
        }
        return true;
    }
    else if(x<0 || y<0 || x>=n || y>=n || maze[x][y]==0 || sol[x][y]==1)
    {
        return false;
    }
    
    sol[x][y]=1;

    bool up=rinm(maze,sol,n,x-1,y);
    bool down=rinm(maze,sol,n,x+1,y);
    bool right=rinm(maze,sol,n,x,y+1);
    bool left = rinm(maze,sol,n,x,y-1);
   
    sol[x][y]=0;

    if(up||down||right||left)
    {
        return true;
    }
    return false;
}

要打印到目的地的任何一条路径,您可以保留一个全局变量并在找到任何路径时初始化该变量,然后如果该变量已初始化,则再次返回 false。下面是一个路径路径的代码。
int c = 0;
bool rinm(int** maze,int** sol,int n, int x, int y)
{
    if(x==n-1 && y==n-1)
    {
        c = 1;
            sol[x][y]=1;

        //print the path
        for (int i = 0; i < n; ++i)
        {
            /* code */
            for (int j = 0; j < n; ++j)
            {
                cout<<sol[i][j]<<" ";

            }

            cout<<endl;
        }
        return true;
    }
    else if(x<0 || y<0 || x>=n || y>=n || maze[x][y]==0 || sol[x][y]==1 || c == 1)
    {
        return false;
    }

    sol[x][y]=1;

    bool up=rinm(maze,sol,n,x-1,y);
    bool down=rinm(maze,sol,n,x+1,y);
    bool right=rinm(maze,sol,n,x,y+1);
    bool left = rinm(maze,sol,n,x,y-1);
   
    sol[x][y]=0;

    if(up||down||right||left)
    {
        return true;
    }
    return false;
}

为了便于理解,这里列出了一些变化。

【讨论】:

  • 但是对于 n=4 1 0 0 0 1 1 1 1 1 0 1 1 1 0 1 1 的好友,我使用此代码获得了额外的输出。
  • @BikramjitDas 你能发一些截图吗,因为我只得到了上述测试用例的一个输出。我得到的输出是`1 0 0 0 1 1 1 0 0 0 1 0 0 0 1 1 '
【解决方案2】:

避免使用原生二维数组。用简单的 1d valarray 或向量替换它们,并使用您自己的简单方法访问它的元素,该方法将 x 和 y 坐标转换为简单的索引。你会从许多头痛中解脱出来......

class Maze
{
    private:
    std::valarray<int> _data;
    int _width, _height;

    public:
    Maze(int width, int height) : _data(width * height)
    {
        _width = width;
        _height = height;
    }

    int& item(int x, int y)
    {
        return _data[y * _width + x];
    }

    // ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多