| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 8608 人关注过本帖, 3 人收藏
标题:小杰作--找迷宫出口路线
只看楼主 加入收藏
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
“if (n[x][y]=='o')n[x][y]=' ';   //这句加得可以吧~”
这句加不得的,只能在完全退出递归后才能还原地图,否则随便给个数据范例就陷入死循环。
2016-12-20 13:29
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 11楼 xzlxzlxzl
看来x版主递归还没有学得够火候哦我是通过测试才拿出来的~
前面有个重要条件

 if (n[x][y]!=' ')
        return 0;

加这句是为了避免输出经过退格的路线,你可以去测试一下,看看有没有问题~

对哦,你写的代码末尾加了这句那无论怎么变动四个方向的权值都可以避免输出退格(虽然这样并不能保证走的是最短路径)~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 13:41
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
那你测试这个数据吧!至少我清楚自己写的递归在什么情况下限于死循环。
       char K[N][N]=   
     {
        {"**********"},
        {"*  S*  *E*"},
        {"* *** ****"},
        {"* * *  * *"},
        {"          "},
        {"          "},
        {"          "},
        {"          "},
        {"          "},
        {"          "},
     };
2016-12-20 13:44
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
理论上只要空间够一个“口”字形面积,在递归退出前还原经过的路线,就会陷入死循环。
2016-12-20 13:49
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 13楼 xzlxzlxzl
好吧,你是正确的~我还要再修改一下才行(看来我还是不应该删我原来的代码啊)~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 13:49
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 15楼 九转星河
把源码改回来了

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 14:01
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
多谢炎天版主置顶

想不到炎版主也这么重视我的杰作,很感动哦

这个迷宫我先研究一下,有时间再更新~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 20:52
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 13楼 xzlxzlxzl
哈哈,果然是理论上的"死循环"啊,其实,没有绝对的死循环,只不过这种方法当遇到新出路时会把原来走过的样板全部刷新,导致循环次数呈几何级别增长~貌似陷入"死循环",你可以拿下列代码测试一下~结果会很有趣的诶,我现在都会放动画了~

程序代码:
#include<stdio.h>//迷宫路径测试代码
#include<stdlib.h>
#define N 11
int COUNT=-1;//计算起点和终点间的步数,如果不存在通向终点的路径,则保留初值-1
typedef struct Node
{
    int x;
    int y;
}Node;
Node run[N*N]={0};
void print(char K[][N])
{
    int i=0;

     for (i=0;i<N;i++)
        printf("%s\n",&K[i][0]);
}
int go(char n [][N],Node run[],int x,int y,int step)
{
    system("cls");
    print(n);

    if (x<0||x>=N||y<0||y>=N)
        return 0;

    if (n[x][y]=='E')
    {
        COUNT=step;
        return 1;
    }

    if (n[x][y]!=' ')
        return 0;

    n[x][y]='o';

    run[step].x=x;
    run[step].y=y;

    if (go(n,run,x-1,y,step+1))
        return 1;

    if (go(n,run,x+1,y,step+1))
        return 1;

    if (go(n,run,x,y-1,step+1))
        return 1;

    if (go(n,run,x,y+1,step+1))
        return 1;

    if (n[x][y]=='o')
        n[x][y]=' ';

    return 0;
}
int main()
{
  char K[N][N]=    
     {
        {"**********"},
        {"*  S*  *E*"},
        {"* *** ****"},
        {"* * *  * *"},
        {"          "},
        {"****      "},
        {"    ******"},
        {"          "},
        {"          "},
        {"          "},
     };


     int i=0;
     int j=0;
     int step=0;

     for (i=0;i<N;i++)
     {
         for (j=0;j<N&&K[i][j]!='S';j++);
         if (j<N)
             break;
     }

    K[i][j]=' ';

    if (go(K,run,i,j,step))
        printf("Yes\n");
    else
        printf("NO\n");

    K[i][j]='S';

  //  for (i=0;i<N;i++)
  //      for (j=0;j<N;j++)
  //          if (K[i][j]=='o')
   //             K[i][j]=' ';

  //  for (i=0;i<COUNT;i++)
  //      K[run[i].x][run[i].y]='o';

    for (i=0;i<N;i++)
        printf("%s\n",&K[i][0]);

    printf("The step(s) is: %d\n",COUNT);

    printf("The Road is:\n");

    for (i=0;i<COUNT;i++)
    {
        printf("[%d][%d] ",run[i].x,run[i].y);

        if (i%10==9&&i!=COUNT-1)
            printf("\n");
    }

    printf("\n");

    return 0;
}

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-21 01:04
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
这个是求迷宫的最短路径的代码~注意,当迷宫开口很大(像13楼那样)循环遍历次数就会超多,看上去貌似陷入(死循环)]~当然迷宫路径只有几条的时候求最优解是可以的~对比删了

if (n[x][y]=='o')
    n[x][y]=' ';

和保留,step的值是会有不同的~

这个是求最短路径的代码~

程序代码:
#include<stdio.h>//注意,迷宫节点不能太多,会影响执行效率
#include<stdlib.h>
#include<string.h>
#define N 11
int COUNT=-1;//计算起点和终点间的步数,如果不存在通向终点的路径,则保留初值-1
typedef struct Node
{
    int x;
    int y;
}Node;
Node run[N*N]={0};
Node run_2[N*N]={0};
void print(char K[][N])
{
    int i=0;

     for (i=0;i<N;i++)
        printf("%s\n",&K[i][0]);
}
int go(char n [][N],Node run[],int x,int y,int step)
{

    if (x<0||x>=N||y<0||y>=N)
        return 0;

    if (n[x][y]=='E'&&(COUNT==-1||step<COUNT))
    {
        int i=0;

        COUNT=step;

        for (i=0;i<COUNT;i++)
            run_2[i]=run[i];

        return 0;
    }
    else if (n[x][y]=='E')
        return 0;

    if (n[x][y]!=' ')
        return 0;

    n[x][y]='o';

    run[step].x=x;
    run[step].y=y;

    if (go(n,run,x-1,y,step+1))
        return 1;

    if (go(n,run,x+1,y,step+1))
        return 1;

    if (go(n,run,x,y-1,step+1))
        return 1;

    if (go(n,run,x,y+1,step+1))
        return 1;

    if (n[x][y]=='o')
        n[x][y]=' ';

    return 0;
}
int main()
{
  char K[N][N]=    
    {
        {"**********"},
        {"*  S*  *E*"},
        {"* *** ** *"},
        {"* * *  * *"},
        {"*        *"},
        {"*** * ** *"},
        {"**  *    *"},
        {"** ** ** *"},
        {"*        *"},
        {"**********"},
    };



     int i=0;
     int j=0;
     int step=0;

     for (i=0;i<N;i++)
     {
         for (j=0;j<N&&K[i][j]!='S';j++);
         if (j<N)
             break;
     }

    K[i][j]=' ';

    go(K,run,i,j,step);

    K[i][j]='S';

    for (i=1;i<COUNT;i++)
        K[run_2[i].x][run_2[i].y]='o';

    for (i=0;i<N;i++)
        printf("%s\n",&K[i][0]);

    printf("The step(s) is: %d\n",COUNT);

    printf("The Road is:\n");

   for (i=0;i<COUNT;i++)
    {
        printf("[%d][%d] ",run_2[i].x,run_2[i].y);

        if (i%10==9&&i!=COUNT-1)
            printf("\n");
    }

    printf("\n");

    return 0;
}


[此贴子已经被作者于2016-12-21 02:17编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-21 01:29
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
回复 18楼 九转星河
  嗯,有探索精神是好的,但钻牛角尖就不对了。
  你这个转出来的实例是2*3,并没有一个口字型面积,口字型面积最低得3*3。我之所以说是理论上的,因为当探测点位于口子中心时,由于该点的标记‘o’被清除,导致该点的子点重新将父点做为新路径重复走,这个过程就永远重复下去形成死循环。
  当然由于递归设计方式不同,可能造成死循环的方式也不一样,像我这种递归属于深度递归,如果像你这样把标记‘o’在递归退出前用空格还原,那么最先进去的点最后被空格代替,发生效率低下的重复或死循环的一般是在大面积网格的情况下,当一个无路可走的点会直接退出当前递归,这个点就被空格还原,但退出这一步时它可能有成为父递归的合格点,如是低效率的重复或死循环发生了。
  当推测递归效率或是否发生死循环时,我多只是在头脑中模拟,设置的条件只是规避这些发生,并没有进行很多反向的实验(明知有低效率或死循环发生而为之)。经验证,你如果对走过的路径进行还原的话,在空格面积为7*7时基本算是死循环了
  如果是为了还原地图,你完全可以在递归完成后用一个循环吧字符‘o’用空格替换,如果是为了获取最短路径,这个递归算法难以完成,百度到很多算法,如什么“Dijkstra”“Floyd-Warshall”等,要花时间接受别人的思想,还不如自己想一个。我目前想到的是用四叉树的方法,但一想到要用链表头就大,临近期末考试了,很难有足够时间构思了,等闲下来再说吧。
  10:30再更:
  对了,像我这种深度递归,即使不做空格还原操作,在空格面积大于500*500时,也会发生栈溢出错误,除非编译时将栈空间扩大。
  有点啰嗦啊!以上!

[此贴子已经被作者于2016-12-21 10:31编辑过]

2016-12-21 09:45
快速回复:小杰作--找迷宫出口路线
数据加载中...
 
   



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

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