【问题标题】:Issue solving Maze with Backtrack使用回溯解决迷宫问题
【发布时间】:2014-02-28 21:57:53
【问题描述】:

我有一个通过 txt 文件接收迷宫的项目,我必须解决它。 唯一难以解决的规范是:没有其他二维数组(无复制,无布尔)。

所以我使用堆栈和回溯来解决它。我使用了两个堆栈,一个用于复制访问过的房间,另一个用于复制路径。但问题是当我回到主函数时,这两个堆栈只得到了他们在迷宫中的最后一个位置。所以这就是我的问题,我刚刚拿到了我的堆栈中的最后一个位置。

当我在回溯函数中时,还有另一个函数检查我之前是否在那个位置,我测试了我之前提到的堆栈,并且工作正常(保存访问过的房间的堆栈),我打印了所有值这个堆栈的。

我不知道为什么主函数不能接收完整的堆栈(至少对于访问的房间),路径堆栈根本不起作用。

bool path(ColaD* colaDG, Node* temp, PileD* pileDG)
{
    if (temp->row == colaDG->end->row && temp->col == colaDG->end->col)
        return true;
    if (check(pileDG, temp) || mat[temp->row][temp->col] == 1)
    {
        // call check function
        return false;
    }
    pileDG->push(*temp);
    if (temp->row != 0)
    {
        temp->row -= 1;
        colaDG->push(*temp);
        if (path(colaDG, temp, pilaDG))
        {
            return true;
        }
        temp->row += 1;
    }
    if (temp->row != n - 1)
    {
        temp->row += 1;
        colaDG->push(*temp);
        if (path(colaDG, temp, pilaDG))
        {
            return true;
        }
        temp->row -= 1;
    }
    if (temp->col != 0)
    {
        temp->col -= 1;
        colaDG->push(*temp);
        if (path(colaDG, temp, pilaDG))
        {
            return true;
        }
        temp->col += 1;
    }
    if (temp->col != m - 1)
    {
        temp->col += 1;
        colaDG->push(*temp);
        if (path(colaDG, temp, pilaDG))
        {
            return true;
        }
        temp->col -= 1;
    }
    return false;
}
bool check(PileD* pileDG, Node* temp)
{
    // Function to check visited rooms
    bool flag = false;
    Node * recor;
    recor = new Node();
    recor = pileDG->top;
    while (recor != NULL)
    {
        if (recor->row == temp->row && recor->col == temp->col)
        {
            // if already here, return true
            flag = true;
            break;
        }
        else
            recor = recor->pre;
    }
    return flag;
}

我知道,我必须更改路径堆栈,但无论如何都无法正常工作。

想用graph来解决,但是完全不知道怎么实现graph。对不起我的英语,我不是以英语为母语的人。我试图将一些单词更改为代码,因为有些单词是西班牙语。任何帮助都会很棒。并且对不起.cpp文件中的整个代码,我只是在测试,真正的项目会有所不同。

完整代码:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;

int n=0,m=0;
int **mat;

class Node{
public:
        Node(){pre=NULL;}
        int row;
        int col;
        Node *pre;
};

class ColaD{
   public:
        ColaD(){fin=fte=end=NULL;}
        void push(Nodo xdato);
        void pop();
        Node *fte,*fin,*end;
};
void ColaD::push(Node xdato){
     Node *nuevo;
     nuevo = new Node();
     if(nuevo){
          (*nuevo)= xdato;
          nuevo->pre = NULL;
          if(!fte)
             fte = nuevo;
          else
             fin->pre=nuevo;
          fin = nuevo;
     }
}
void ColaD::pop(){
     Node *elim; 
     if(fte){
        elim = fte;
        if(fte==fin)
           fte = fin = NULL;
        else
            fte = fte->pre;
        delete(elim);
     }
}
class PileD{
   public:
        PileD(){tope=NULL;}
        void push(Node xdato);
        void pop();
        Node *tope;
};
void PilaD::push(Node xdato){
        Node *nuevo;
        nuevo = new Node;
        if(nuevo){
          (*nuevo)=xdato;
          nuevo->pre=tope;
          tope=nuevo;
        }
}
void PileD::pop(){
        Node *aux;
        if(tope){
          aux=tope;
          tope=tope->pre;
          free(aux);    
        }
}

void tamMat(); //read the size of the maze given by a txt file
void loadM(); //once i know the size, and the bi dimensional is created I set the values to de bi dimensional A.
void printM(); //Just check the values
bool path(ColaD *colaDG,Node *temp,PileD *pileDG); 
bool check(PileD *pileDG,Node *temp);


int main(int argc, char const *argv[])
{
        ColaD *colaDG;
        Node *inicio;
        PileD *pileDG;
        tamMat();  //Read the size
        mat = new int*[n];
        for(int i=0;i<n;i++)
         mat[i]=new int[m];

    loadM(); //Set values given from the file
    colaDG = new ColaD();
    pileDG = new PileD();
    inicio = new Node();
    inicio->row=0;  //Proyect says, the start of the maze is in the first row of the maze
    for(int j=0;j<m;j++)
        if(mat[0][j]!=1){
                inicio->col=j; //Found the position in the row
                break;
            }
    colaDG->end = new Nodo();
    colaDG->end->row=n-1; //End position is in the last row
    for(int j=0;j<m;j++)
        if(mat[n-1][j]!=1){
                colaDG->end->col=j; //Found the position
                break;
            }
        bool b = path(colaDG,inicio,pilaDG); //call my backtrack function
        getchar();
        /* CODE TO CHECK visited Rooms
        Nodo *temp = new Nodo();
        temp=pileDG->tope;
        while(temp!=NULL){
            cout << temp->row <<" "<<temp->col << endl;
            getchar();
            temp->pre;                         
        }
        */
        getchar();

        return 0;
}

void tamMat(){ 
        fstream inFile;
        int num;
        n=m=0;
        inFile.open("mat.txt",ios::in);
        string line;

        getline(inFile,line);
        stringstream temp(line);
        while(temp>> num)
                m++;
        n++;
        while(getline(inFile,line))
                n++;
        inFile.close();
}
void loadM(){
        fstream inFile;
        inFile.open("mat.txt",ios::in);
        for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                        inFile >> mat[i][j];
        inFile.close();
}

void printM(){
        for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
           if(mat[i][j]!=1)
                         cout << " ";
           else
             cout << mat[i][j];
           cout << " ";
        }
                cout << endl;
        }
}
bool path(ColaD *colaDG,Node *temp,PileD *pileDG){

    if(temp->row==colaDG->end->row && temp->col==colaDG->end->col) return true;
    if(check(pileDG,temp) || mat[temp->row][temp->col]==1){
          return false;      
    }
    pileDG->insertar(*temp);
    if(temp->row!=0){
         temp->row-=1;
         colaDG->insertar(*temp);            
         if(path(colaDG,temp,pileDG)){
              return true;
         }
         temp->row+=1;
    }
    if(temp->row!=n-1){
         temp->row+=1;
         colaDG->insertar(*temp);
         if(path(colaDG,temp,pileDG)){
              return true;
         }
         temp->row-=1;          
    }
    if(temp->col!=0){
         temp->col-=1;
         colaDG->insertar(*temp);
         if(path(colaDG,temp,pileDG)){
              return true;
         }
         temp->col+=1;    
    }
    if(temp->col!=m-1){     
         temp->col+=1;
         colaDG->insertar(*temp);
         if(path(colaDG,temp,pileDG)){
              return true;
         }
         temp->col-=1;       
    }
    return false;
}
bool check(PileD *pileDG,Node *temp){
     bool flag=false;
     Node *recor;
     recor = new Node();
     recor = pileDG->tope;
     while(recor!=NULL){
          if(recor->row==temp->row && recor->col==temp->col){
              flag=true;
              break;
          }
          else
              recor=recor->pre;
     }
     return flag;
}

迷宫 mat.txt 文件。

0 0 0 1 1 1 1 1 1 1
1 1 0 1 0 5 1 1 0 1
1 1 6 1 7 1 1 1 0 1
1 1 0 1 0 1 0 0 0 1
1 0 9 0 0 1 0 1 0 1
1 8 1 1 0 1 6 1 0 1
1 0 1 1 0 1 0 1 5 1
1 0 1 1 0 1 0 1 0 1
1 0 0 1 0 0 0 1 7 1
1 1 1 1 1 1 1 1 0 1
1=Walls / 0=Free Space / Other numbers = Bonus

【问题讨论】:

  • 在页面右侧的相关列中似乎有一些与您的问题非常相似的问题......这是第一个......不确定这是否有帮助,但看到一对夫妇有同题,必有你的答案。

标签: c++ stack backtracking maze


【解决方案1】:

你的代码有很多问题,有些很重要,有些只是效率问题。我现在可以看到的主要问题不在您的分析代码中,而是在您的诊断代码中。

看评论里的部分:

    /* CODE TO CHECK visited Rooms */
    Nodo *temp = new Nodo();
    temp=pileDG->tope;
    while(temp!=NULL){
        cout << temp->row <<" "<<temp->col << endl;
        getchar();
        temp->pre;
    }

右大括号前的最后一行是

        temp->pre;

它只是从*temp 对象中读取pre 字段,但使用那个值——temp 变量没有被修改,所以程序永远停留在循环中,打印一遍又一遍的相同数据。

我猜

        temp = temp->pre;

就是你的意思。

无论如何,如果您使用for 而不是while,这样的循环更容易编写和阅读:

    /* CODE TO CHECK visited Rooms */
    for( Nodo *temp=pileDG->tope; temp!=NULL; temp=temp->pre){
        cout << temp->row <<" "<<temp->col << endl;
        getchar();
    }

一旦你替换它,你可能会看到代码的(一些)其他问题。例如,您可能会在打印的输出中发现太多“已访问”位置。

【讨论】:

  • 天哪,我不敢相信这是我的错误,我感觉很菜鸟......我看了你过去的回复,只是没有时间回答。现在可以工作,感谢您的宝贵时间,我知道我的代码有一些(或很多)效率问题,我仍然是这个疯狂世界的初学者。现在我可以继续我的项目了,再次感谢我的朋友。
【解决方案2】:

这部分代码发生了什么?

Node * recor;
recor = new Node();
recor = pileDG->top;

新节点不是永远丢失了吗...?

您似乎将访问的每个新点都放入了colaDG 堆栈。但是,当您从死胡同返回时,我看不到您删除点的位置...

【讨论】:

  • 不要永远丢失,因为如果你看到旁边的代码,你可以检查一下,temp=temp->pre;这是主节点的前身。如果你去 check() 函数,你可以尝试打印 temp->row 和 temp->col;几乎是相同的代码。是的,我需要删除它,我必须将堆栈类型更改为列表,但无论如何,我删除了那些代码(我弹出堆栈的位置),只是为了测试它们是否将位置推入堆栈,但仍然没有推任何东西,只是最后一个位置。
  • @vitaR,让我解释一下:我上面复制的三行的第一行声明了一个名为recor的变量,以保存指向Node类对象的指针;第二行创建一个新的 Node 对象并将指向该对象的指针存储在 recor 变量中;第三行从pileDG-&gt;top 成员变量中读取一个指向其他 Node 对象的指针,并存储指向同一变量recor 的指针。这样,指向新创建的Node 对象的指针就会被覆盖。由于它没有存储在任何其他地方,程序无法再访问创建的Node 对象 - 它丢失了。
猜你喜欢
  • 2015-08-31
  • 1970-01-01
  • 2014-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
相关资源
最近更新 更多