| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 8606 人关注过本帖, 3 人收藏
标题:小杰作--找迷宫出口路线
只看楼主 加入收藏
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
用递归完成的,看上去比22楼代码简练,但实际上递归效率远低于循环效率,主要是深层递归时极有可能绕回来将一个本来层级值很小的设置成层级值很大,当然最终会设置正确,但已经降低效率了,代码如下,有些用于调试的代码可以去掉:
程序代码:
#include<stdio.h>
#define N 11
void setlevel(int a[][N],int x,int y,int l)
{//设置指定坐标点层级,如果坐标点是出口则返回1,否则返回0
    int i;
    if(x<0||x>=N-1||y<0||y>=N-1||a[x][y]>N*N)return;       //坐标不合格或碰到墙及出口退出递归
    if(a[x][y]>l)a[x][y]=l;                            //要设置的层级小于已设置层级则设置,否则返回
    else return;
    for(i=1;i<9;i+=2)setlevel(a,x+i/3-1,y+i%3-1,l+1);  //递归设置层级,这个步进算法很巧妙哦!
}
int findmin(int a[][N],int x,int y)
{//找坐标点周边层级最小的,找到后返回步进矢量
    int i,j,k,x1,y1;
    j=a[x][y];
    for(i=1,k=0;i<9;i+=2)
    {
        x1=x+i/3-1;
        y1=y+i%3-1;
        if(x1>=0&&y1>=0&&x1<N&&y1<N&&a[x1][y1]!=N*N&&a[x1][y1]<j)
        {
            k=i;
            j=a[x1][y1];
        }
    }
    return k;
}

int shortpath(char a[][N])
{//找最短路径,找到则标注并返回1,否则返回0
    int i,j,m;
    int sx,sy,ex,ey,b[N][N];
    sx=sy=ex=ey=-1;
    for(i=0;i<N;i++)
    {
        for(j=0;j<N;j++)
        {
            b[i][j]=N*N;
            if(a[i][j]=='S')
            {
                sx=i;
                sy=j;                         //记录入口坐标
            }
            if(a[i][j]=='E')
            {
                ex=i;
                ey=j;                         //记录出口坐标
                b[i][j]=N*N+1;
            }
            if(a[i][j]=='*')b[i][j]=N*N+2;
        }
    }
    if(sx<0||sy<0||ex<0||ey<0)return 0;       //没有出入口返回无路径
    setlevel(b,sx,sy,1);
    j=findmin(b,ex,ey);
    if(!j)return 0;                           //路堵死了返回无路径
    m=b[ex+j/3-1][ey+j%3-1];
    while(ex!=sx||ey!=sy)
    {
        j=findmin(b,ex,ey);
        if(!j)return 0;                       //路径意外错误返回无路径,这种情况肯定不会出现,可去掉
        ex=ex+j/3-1;
        ey=ey+j%3-1;
        if(a[ex][ey]!='S')a[ex][ey]='o';
    }
    for(i=0;i<N;i++)
    {
        for(j=0;j<N;j++)printf("%4d",b[i][j]);
        printf("\n");
    }  //输出数据化的地图用于调试递归调用后的结果是否正确,正常后可去掉

    return m;
}

int main()
{
    char k[N][N]=    
    {
        {"          "},
        {"   S      "},
        {"          "},
        {"          "},
        {"          "},
        {" **** ****"},
        {"          "},
        {"          "},
        {"          "},
        {"        E "},
    };
    int i,m;
    for(m=0;m<N;m++)printf("%s\n",&k[m][0]);      //显示未标注路径的地图
    if((i=shortpath(k)))
    {
        printf("Yes,最少 %d 步完成。\n",i);
        for(m=0;m<N;m++)printf("%s\n",&k[m][0]);  //显示标注路径的地图
    }
    else printf("No\n");
    return 0;
}


[此贴子已经被作者于2016-12-22 11:15编辑过]

2016-12-22 10:24
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 31楼 xzlxzlxzl
这个虽然不及广度循环遍历效率高,但毕竟是通过深度递归做出来的,是个好东西我先收藏,有时间再慢慢消化~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-22 10:31
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
回复 32楼 九转星河
有一个逻辑关系搞错了,语句“while(ex!=sx&&ey!=sy)”应修改为“while(ex!=sx||ey!=sy)”,否则显示路径出错,已修正。
至于本帖其他题目,只能看有没有时间。我之所以死盯最优路径,源于我高中时想做“老鼠走迷宫游戏”,后因过于沉迷被斥不务正业,掐断了一切和电脑编程有关事项,上大学后居然提不起兴趣,终未竟,于今算是补上了。

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

2016-12-22 10:36
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 33楼 xzlxzlxzl
虽然我没仔细看程序的性能,但我感觉是先把迷宫所有路标都遍历一遍,然后做个深度标记~遍历完毕再后续处理深度标记~我的想法是这样的,不知道你的算法是不是这样~如果是的话,那我就消化容易很多了~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-22 10:43
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
回复 34楼 九转星河
递归嘛,就setlevel函数那么一点点,总共不超过5句,但要理解它到底怎样完成工作的,需要你善于“头脑风暴”,比较烧脑,很容易走火入魔。
11:20更:由于普通数组和字符串数组的区别,在字符串中看似无出路的情况下,普通数组会将字符串结束符作为出路,导致错误,为避免对递归函数坐标合格判断做了修改。

[此贴子已经被作者于2016-12-22 11:18编辑过]

2016-12-22 11:01
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 35楼 xzlxzlxzl
我的理解是这样的,画程序较为花时间,我先在这里比划一下~

假设递归遍历深度标记为(0为墙)

1 2 3 12 11
0 0 4 0 10
0 0 5 0 9
0 0 6 7 8

由于3和12是连通的并且深度不是相差1,那么12就可以用4来代替,11就可以用5代替,直到所有深度标记都相差1~然后再从终点根据优化后的递归深度相差1逆推回起点,即为最短路径~就像22楼的算法一样,巧妙利用了已知点的深度递减只有唯一一条路径~
14:40更:已知点的深度递减只有唯一一条路径~说法有误如果当最短路径不唯一时这个说法是不成立的~
深度优化后则为:

1 2 3 4 5
0 0 4 0 6
0 0 5 0 7
0 0 6 7 8

核心部分不是在递归--递归只是一种标记路径的方法,而是在后续优化递归深度部分~

[此贴子已经被作者于2016-12-22 14:38编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-22 11:20
hykj9495
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:4
帖 子:796
专家分:1441
注 册:2016-6-6
收藏
得分:0 
两位接力,我学习下。完全看不懂

慢慢调试
2016-12-23 11:18
dongdon923
Rank: 2
等 级:论坛游民
威 望:1
帖 子:17
专家分:58
注 册:2016-12-2
收藏
得分:0 
看来。真的要学习算法了。
2017-01-01 16:29
快速回复:小杰作--找迷宫出口路线
数据加载中...
 
   



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

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