C++ 回溯式问题解决迷宫
我有一个项目,通过txt文件接收迷宫,我必须解决它。 唯一难以解决的规范是:没有其他二维数组(没有拷贝,没有Bool) 所以我使用堆栈和回溯来解决它。我使用两个堆栈,一个用于复制访问的房间,另一个用于复制路径。但问题是,当我回到主函数时,两个堆栈只得到了它们在迷宫中的最后一个位置。这就是我的问题,我刚刚拿到了最后一个位置 当我使用回溯函数时,还有另一个函数检查我之前是否处于该位置,我测试了我前面提到的堆栈,工作正常(保存访问过的房间的堆栈),我打印了该堆栈的所有值 我不知道为什么主函数不能接收完整的堆栈(至少对于访问过的房间),路径堆栈根本不起作用C++ 回溯式问题解决迷宫,c++,stack,backtracking,maze,C++,Stack,Backtracking,Maze,我有一个项目,通过txt文件接收迷宫,我必须解决它。 唯一难以解决的规范是:没有其他二维数组(没有拷贝,没有Bool) 所以我使用堆栈和回溯来解决它。我使用两个堆栈,一个用于复制访问的房间,另一个用于复制路径。但问题是,当我回到主函数时,两个堆栈只得到了它们在迷宫中的最后一个位置。这就是我的问题,我刚刚拿到了最后一个位置 当我使用回溯函数时,还有另一个函数检查我之前是否处于该位置,我测试了我前面提到的堆栈,工作正常(保存访问过的房间的堆栈),我打印了该堆栈的所有值 我不知道为什么主函数不能接收完
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;
}
我必须更改路径堆栈,我知道,但无论如何都不起作用
我想用图形来解决这个问题,但我根本不知道如何实现图形。对不起,我的英语不是以英语为母语的。我试着把一些单词改成代码,因为有些单词是西班牙语的。任何帮助都会很好。对于.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;
}
这部分代码中发生了什么
Node * recor;
recor = new Node();
recor = pileDG->top;
新节点不是永远丢失了吗
您似乎将访问的每个新点都放在
colaDG
堆栈上。但是,我看不出当您从死胡同路径回溯时,您从何处删除了这些点…您的代码存在许多问题,其中一些问题很重要,一些只是效率问题。我现在看到的主要问题不是分析代码,而是诊断代码
请看评论中的部分:
/* 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
变量,因此程序永远停留在循环中,一次又一次地打印相同的数据
我想
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();
}
/*检查已访问房间的代码*/
对于(Nodo*temp=piledge->tope;temp!=NULL;temp=temp->pre){
在页面右侧的相关列中,似乎有一些问题与您的问题非常相似…这是第一个问题…不确定这是否有帮助,但鉴于一对夫妇有相同的标题,其中一个肯定会有您的答案。不要永远丢失,因为如果您看到旁边的代码,您可以检查是否有,temp=temp->pre;这是是主节点的前一个。如果您转到check()函数,您可以尝试打印temp->row和temp->col;几乎是相同的代码。是的,我需要删除它,我必须将堆栈类型更改为列表,但无论如何,我删除了这些代码(在弹出堆栈的地方),只是为了测试他们是否将该位置推送到堆栈,但仍然没有推送任何东西,只是最后一个位置。@vitaR,让我解释一下:我上面复制的三个位置中的第一行声明了一个名为recor
的变量,以保留指向类Node
对象的指针;第二行创建一个新的Node对象并存储指向t对象;第三行从piledge->top
成员变量读取指向其他节点
对象的指针,并存储指向同一变量的指针recor
。这样,指向新创建的节点
对象的指针就会被覆盖。因为它没有存储在任何其他变量中r place,程序无法再访问创建的节点
对象-它丢失了。天哪,我不敢相信这是我的错误,我感觉很不舒服…我读了你过去的回复,只是没有时间回答。现在可以了,谢谢你抽出时间,我知道我的代码有一些(或很多)效率问题,我仍然是这个疯狂世界的初学者。现在我可以继续我的项目了,再次感谢我的朋友。
temp->pre;
temp = temp->pre;
/* CODE TO CHECK visited Rooms */
for( Nodo *temp=pileDG->tope; temp!=NULL; temp=temp->pre){
cout << temp->row <<" "<<temp->col << endl;
getchar();
}