查找迷宫C ++中是否存在路径

时间:2018-07-20 11:36:44

标签: c++ c++11 backtracking

我的代码给了我运行时错误。我不知道该如何解决? 它甚至不适用于较小的矩阵4 X 4。问题的矩阵大小不超过20 x 20。

代码:

#include <iostream>
using namespace std;
int a[20][20];
bool findpath(int ar[][20],int i,int j,int size)
{
    if (ar[i][j]==0 || i>(size-1) || j>(size-1) || i<0 || j<0)
        return false;
    if (ar[i][j]==2)
        return true;
    if ((findpath(ar,i+1,j,size)) || (findpath(ar,i,j+1,size)) 
    || (findpath(ar,i-1,j,size)) || (findpath(ar,i,j-1,size)))
        return true;
    return false;
}
int main() {
    int t;
    cin>>t;
    while(t--)
    {   int n;
        cin>>n;

        int r,c;

        //size = n;
        for(int i =0 ;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                cin>>a[i][j];
                if (a[i][j]==1)
                   { r=i;
                    c=j;
                   }
            }

        }
        //cout<<r<<c;
        bool b = findpath(a,r,c,n);
        if (b)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;

    }
    return 0;
}

输入:

1
4
3 0 0 0 0 3 3 0 0 1 0 3 0 2 3 3 

输出:

YES

但是我得到Segmentation Fault (SIGSEGV)

1 个答案:

答案 0 :(得分:1)

检查对语句if (ar[i][j]==0 || i>(size-1) || j>(size-1) || i<0 || j<0)的求值顺序。即使i超出范围或j超出范围,您也将访问ar [i] [j]来评估第一个表达式。顺序应如此,以便在if条件下发生短路时,您是安全的/不会导致不确定的行为,例如:

if (i < 0 || i >= size || j < 0 || j >= size || ar[i][j]==0)。现在,如果i < 0陷入僵局,则无需检查其余部分,并且不评估ar[i][j]

正如您提到的那样,这是行不通的,下面是一个有效的版本,我将向您解释。首先,我将您的C样式数组更改为向量,而是使用它们来获取行和列的大小。我还从用户中删除了您的输入,您可以在以后添加这些输入,并有助于使问题保持​​简单。

#include <vector>
bool findpath(vector<vector<int>>ar,int i,int j,vector<vector<int>>& visited)
{

    if (i < 0 || i >= ar.size() || j < 0 || j >= ar[0].size() || ar[i][j] == 0 || visited[i][j]) return false;

    if (ar[i][j]==2) return true;

    visited[i][j] = true;
    if(findpath(ar,i+1,j,visited) || findpath(ar,i,j+1,visited) || findpath(ar,i-1,j,visited) || findpath(ar,i,j-1,visited)) return true;
    visited[i][j] = false;

    return false;
}
int main() {
        const int rows = 3;
        const int cols = 3;
        vector<vector<int>> arr = {{ 0 , 3 , 2 },
                                   { 3 , 3 , 0 },
                                   { 1 , 3 , 0 }};

        vector<vector<int>> visited(rows,vector<int>(cols,false));
        bool b = findpath(arr,1,1,visited);
        if (b)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;


    return 0;
}

在主要功能中,我仅使用vector<vector<int>>来描述您发布的链接中的迷宫。在下面的示例中,ij11的起点。还有一个visited二维数组,与迷宫相同。这样可以通过标记已经覆盖的斑点来阻止您进行无限递归,如果无法解决,您可以将vector[i][j] = false设置为回溯。最后,如果您的安排中的任何一项返回有效结果,我们将返回否则,我们将仅返回false。

您可以观看此演示live here

您还提到1是起点。在示例中,我已经从1开始。您可以在main中添加一个循环,以便首先找出起点的坐标。同样,这应该足以使您前进。