标题:递归的迷宫问题,请问代码错在什么地方
只看楼主
komorebi0110
Rank: 2
来 自:上海
等 级:论坛游民
帖 子:145
专家分:17
注 册:2019-11-23
结帖率:96.88%
已结贴  问题点数:20 回复次数:11 
递归的迷宫问题,请问代码错在什么地方
A maze is to be represented by a 12*12 array composed of three values: Open, Wall, or Exit. There is one exit from the maze. Write a program to determine whether it is possible to exit the maze from the starting point (any open square can be a starting point). You may move vertically and horizontally to any adjacent open square(左右上下四个方向). You may not move to a square containing a wall. The input consists of a series of 12 lines of 12 characters each, representing the contents of each square in the maze. The characters are O, W, or E.
【输入】 12×12的迷宫方阵,每个格子的可能取值有:O, W, or E,输入数据能够确保迷宫只有一个出口。
任意3个起点的坐标,格式如下(x,y)。其中x为纵坐标,y为横坐标,起始坐标从左上角的格子开始,坐标起始值为0.
【输出】
起点到出口的最短路径长度(经过多少个方格),若起点无法到达出口则输出-1。起始节点和结束节点都算入路径长度的计算。

例如:
【输入】
O W O W O W O O W O W O
O W O W W W W O W O O E
O W W W O O O O O O O O
W W W O O O O W W W O W
O O O O W W W O O O O O
O O W O W O W O W O W W
O W W O O O W W O O O W
O O W O O W W W O O O O
O O O W O O O O W W W W
W W W O O O O W W W O O
O W W W W O O O O O W W
W W W O O O O O W W W W
(0,0) (5,7) (7,8)
【输出】
-1 9 10
【解释】
输出表示第一个点(0,0)无法到达出口;
第二个点(5,7)到达出口的最短路径是9;
第三个点(7,8)到达出口的最短路径是10;
搜索更多相关主题的帖子: 输出 the 迷宫 代码 坐标 
2020-04-19 21:08
komorebi0110
Rank: 2
来 自:上海
等 级:论坛游民
帖 子:145
专家分:17
注 册:2019-11-23
得分:0 
#include<stdio.h>
#include<iostream>
using namespace std;
class migong
{  public:
    migong();
    void initial();
    int jisuan();
    void seten();
    void solved(int x,int y,int n);
private:
    int Migong[12][12];
    int step;
    int Ex;
    int Ey;
};
migong::migong()
{
    step=1000000;
}
void migong::initial()
{
    step=1000000;
}
void migong::seten()
{
    for(int i = 0; i<12; i++)
 {
  for(int j = 0; j < 12; j++)
  {
   char temp;
   cin>>temp;
   if(temp=='W')
            Migong[i][j]=1;
            else if(temp=='E')
            {
                Ex=i;
                Ey=j;
                Migong[i][j]=0;
            }
   else if(temp=='O')
    Migong[i][j]=0;
    }
  }


}

void migong::solved(int x,int y,int n)
{
 if(Migong[x][y]!=0)
  return;
 if(x==Ex&&y==Ey)
 {

  step=min(step,n);
  return;
 }
if(x > 0)
solved(x-1,y,n+1);
 if(y > 0)
 solved(x,y-1,n+1);
 if(x < 11)
solved(x+1,y,n+1);
 if(y < 11)
 solved(x,y+1,n+1);
 Migong[x][y]=0;
 return;
}
int migong::jisuan()
{
    return step;
}
int main()
{
    migong A;
    A.seten();
    for(int i=0;i<3;i++)
    {     A.initial();
        int x,y;
        char c;
        cin>>c>>x>>c>>y>>c;
        A.solved(x,y,0);
        if(A.jisuan()==1000000)
            cout << "-1";
   else
    cout << A.jisuan()+1 <<' ';
     }
}

//最近刚学了八皇后问题,知道什么叫回溯...看不出来问题在哪里QAQ

我想要两颗西柚。
2020-04-19 21:11
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:10 
你的递归算法有问题,最后是溢出退出。
迷宫求最短路径适合用广搜,深搜也行,关键是记录步数。我最大限度保留你的代码框架,重新写的递归后代码如下,楼主可参考注释加深理解:
程序代码:
#include<iostream>
using namespace std;
class migong
{
public:
    migong();
    void initial()
    {
        step=200;
        for(int i=0;i<12;i++)
            for(int j=0;j<12;j++)
                if(Migong[i][j]>=0&&Migong[i][j]<step)Migong[i][j]=2000;
    }
    int jisuan();
    void seten();
    void solved(int,int,int);
private:
    int Migong[12][12];
    int step;
};
migong::migong()
{
    step=200;
    //由于最多也只有12*12=144步,同时1000和2000有特殊用途,我的算法要求step初始值只能大于144且小于1000
}
void migong::seten()
{
    for(int i = 0; i<12; i++)
    {
        for(int j = 0; j < 12; j++)
        {
            char temp;
            cin>>temp;
            if(temp=='W')
                Migong[i][j]=-1;
            else if(temp=='E')
                Migong[i][j]=1000;  //出口值
            else if(temp=='O')
                Migong[i][j]=2000;  //通路初始值,求最短路径就必须设置一个大于12*12的值
        }
    }
}

void migong::solved(int x,int y,int n)
{
    int i,j;
    if(x<0||y<0||x>11||y>11||n>step||n>Migong[x][y])return ;  
    //坐标不合格或步数大于坐标位置值或步数大于step返回找下一条路
    if(Migong[x][y]==1000)
    {//找到出口
        step=n;
        return;
    }
    Migong[x][y]=n;
    for(i=0;i<4;i++)
        solved(x-1+(i*2+1)%3,y-1+(i*2+1)/3,n+1);  //四个方向递归
}
int migong::jisuan()
{
    return step;
}
int main()
{
    migong A;
    A.seten();
    for(int i=0;i<3;i++)
    {
        int x,y,c;
        cin>>x>>y;
        A.initial();
        A.solved(x,y,0);
        c=A.jisuan();
        if(c>144)c=-2;
        cout << c+1 <<' ';
    }
    cout << endl;
    return 0;
}

能编个毛线衣吗?
2020-04-19 23:32
forever74
Rank: 12Rank: 12Rank: 12
来 自:CC
等 级:贵宾
威 望:49
帖 子:1636
专家分:3940
注 册:2007-12-27
得分:5 
嗯,楼主的代码会在非墙的走廊里来回走个没完。
所以会溢栈。

对宇宙最严谨的描述应该就是宇宙其实是不严谨的
2020-04-19 23:52
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:0 
回复 3楼 wmf2014
忘了说明,我的输入数据在输入入口坐标是直接输入,不需要单独要cin>>c,具体数据如下:
O W O W O W O O W O W O
O W O W W W W O W O O E
O W W W O O O O O O O O
W W W O O O O W W W O W
O O O O W W W O O O O O
O O W O W O W O W O W W
O W W O O O W W O O O W
O O W O O W W W O O O O
O O O W O O O O W W W W
W W W O O O O W W W O O
O W W W W O O O O O W W
W W W O O O O O W W W W
0 0 5 7 7 8


把这些数据放到一个文本文件里,重定向该文本就可以了,这样调试时就不需要一个个地用键盘输入。

能编个毛线衣吗?
2020-04-20 08:09
return_0
Rank: 8Rank: 8
来 自:五维空间
等 级:禁止访问
威 望:3
帖 子:512
专家分:838
注 册:2020-1-28
得分:5 
重复性剪枝

2020-04-20 09:13
return_0
Rank: 8Rank: 8
来 自:五维空间
等 级:禁止访问
威 望:3
帖 子:512
专家分:838
注 册:2020-1-28
得分:0 
这道题也不适合你的算法,适合搜索算法

2020-04-20 09:18
komorebi0110
Rank: 2
来 自:上海
等 级:论坛游民
帖 子:145
专家分:17
注 册:2019-11-23
得分:0 
//orz虽然不知道什么叫重复性剪枝,但我发现我少写了一行,改了一下能出结果
//我开头写的是什么我也不知道QAQ
#include<stdio.h>
#include<iostream>
using namespace std;
class migong
{  public:
    migong();
    void initial();
    int jisuan();
    void seten();
    void solved(int x,int y,int n);
private:
    int Migong[12][12];
    int step;
    int Ex;
    int Ey;
};
migong::migong()
{
    step=1000000;
}
void migong::initial()
{
    step=1000000;
}
void migong::seten()
{
    for(int i = 0; i<12; i++)
 {
  for(int j = 0; j < 12; j++)
  {
   char temp;
   cin>>temp;
   if(temp=='W')
            Migong[i][j]=1;
            else if(temp=='E')
            {
                Ex=i;
                Ey=j;
                Migong[i][j]=0;
            }
   else if(temp=='O')
    Migong[i][j]=0;
    }
  }


}

void migong::solved(int x,int y,int n)
{
 if(Migong[x][y]!=0)
  return;
 if(x==Ex&&y==Ey)
 {

  step=min(step,n);
  return;
 }
 Migong[x][y]=1;
if(x > 0)
solved(x-1,y,n+1);
 if(y > 0)
 solved(x,y-1,n+1);
 if(x < 11)
solved(x+1,y,n+1);
 if(y < 11)
 solved(x,y+1,n+1);
 Migong[x][y]=0;

}
int migong::jisuan()
{
    return step;
}
int main()
{
    migong A;
    A.seten();
    for(int i=0;i<3;i++)
    {     A.initial();
        int x,y;
        char c;
        cin>>c>>x>>c>>y>>c;
        A.solved(x,y,0);
        if(A.jisuan()==1000000)
            cout << "-1"<<' ';
   else
    cout << A.jisuan()+1 <<' ';
     }
}

我想要两颗西柚。
2020-04-20 15:11
return_0
Rank: 8Rank: 8
来 自:五维空间
等 级:禁止访问
威 望:3
帖 子:512
专家分:838
注 册:2020-1-28
得分:0 
回复 8楼 komorebi0110
重复性剪枝我给你解释一下,先从剪枝算法说起
剪枝剪枝,顾名思义,就是减少搜索算法的可能性(枝叶数),从而加快速度。虽然大家都说“剪枝算法”,但是我个人觉得他不算是算法,常见的剪枝有以下几种:
可行性剪枝
最优性剪枝
重复性剪枝


前二者我就不说了,今天主要是要讲明第三者。

重复性剪枝,就是用flag,或flag数组来防止dfs,bfs等算法的重复,因此得名重复性剪枝。
重复性剪枝一般情况是必须插入的,因为很多情况下如果没有重复性剪枝,就像这道题,你的角色就会在走廊里来回走,后果不堪设想。

这道题正确采用剪枝的方法应该是数组吧,我贴一下核心代码:
在此我说明一下,这道题其实不适合,真的不适合用回溯。我也不写广搜了,这道题最好用dfs(深搜):
vis[x][y]=true;
dfs(x+dx[i],y+dx[i]);
vis[x][y]=false;
dfs套用dfs时按这个方式套用,前面要有一个if,里面说明vis数组为false才能继续探索。

这道题所用的是标记法,非常实用的剪枝,如果还有疑问告诉我哦

2020-04-20 21:25
komorebi0110
Rank: 2
来 自:上海
等 级:论坛游民
帖 子:145
专家分:17
注 册:2019-11-23
得分:0 
回复 9楼 return_0
emmm因为我水平太烂了加上自学能力极弱看得一知半解,现在我数据结构课刚学到递归,dfs我还没接触过,不过这学期应该会讲到这类题,等讲到dfs我应该就能明白了,谢谢大神!

我想要两颗西柚。
2020-04-21 11:28



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-501137-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.211360 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved