迷宫问题探讨!

迷宫问题探讨!

1.搜索空间问题.

对于一个66的迷宫,它的搜索空间是多少?
6
6=36个格子, 每一格的可能搜索方向是4个
根据乘法原理它最大的搜索空间是4^36次方,
这是一个很大的搜索空间,实际上搜索远小于此数.因为搜索的时候
只会沿着通路搜索, 墙被过滤掉了, 搜索空间显著的减小.

2.何为搜索.

搜索就是从庞大的搜索空间中找到一个或全部符合条件的解的过程.
这是搜索广义的概念.

计算机搜索可以理解成构建一个数组的过程,而构建过程为搜索算法.

3.迷宫的表示方法.

迷宫可以用一个2维数组来表示, 0为通路,1为墙.
从入口entry(x1,y1), 找到出口export(x2,y2)的路径为其一个解.
如果找到了一个解,可以把路径中的数值改为2来输出这个2维数组.

4.怎样表示找到了一个解,怎样表示一个搜索路径?

当从入口entry(x1,y1)开始, 依据通道(其值为0)不断搜素,改变x1,y1的值,
当x=x2, y=y2时,表示找到了出口.代表找到了一个解.
找到解后, 必须要根据一个链表,追溯到它的起点, 这个链表就是一个路径.

5.本示例的搜索算法是怎样的?

算法描述: 采用了一个通道队列.

  • 首先, 入口入队列,
  • 然后, 循环执行
    从队列尾部取出一个点, 把它周围的通道(最多三个,最少0个)放入到队列头部
  • 结果判断,
    这样,当iQueuetail 追上iQueueHead 时,表示搜索结束,没有路径.
    或者iQueueHead 找到了出口,输出结果,

找到结果后,可以停止搜索,或继续搜索.

这属于一种宽度优先的搜索算法.

6.代码实例:

#include <stdio.h>
#include <stdlib.h>

#define ROW 15
#define COLUMN 21
/* 定义四周为墙。故为ROW+2,COLUMN+2, 0 为通路,1为墙,-1为搜索过,2为通路路径 */
int gMaze[ROW+2][COLUMN+2]= 
{
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
    {1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,0,0,1,1},
    {1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1,1},
    {1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1},
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
};

typedef struct{
    int i,j; /*4个搜索方向的坐标变化值 */
}Direction;
// 左右上下,注意,此处列值移动为左右,行值移动为上下,直接与MAZE 数组下标运算
Direction gDirect[4]={{0,-1},{0,1},{-1,0},{1,0}};   

typedef struct{
    int x,y;           /*搜索位置的坐标 */
    int pre;           /*表示前驱点的数组位置索引,所有的脚步构成一个数组 */
}Footstep;
#define MAX 500
Footstep gFoots[MAX];  //定义500个脚步数组

void print_result(int tail)
{
    int i,j,k;
    k=tail;
    do
    {
        i=gFoots[k].x; j=gFoots[k].y;
        gMaze[i][j]=2;			// 2 代表是通路路径
        k=gFoots[k].pre;        // 由后继找到它的前趋。
    }while(k);  // 在2维数组中建立一条搜索通路
    /*   
         for(i=1;i<=k;i++)
         {
         gMaze[gFoots[i].x][gFoots[i].y]=2;
         }
         */
    printf("模拟迷宫路径:'>' 表示最后走出迷宫的路径, '@'表示探索过的路径\n");
    printf("进入--\n");
    for (i=1;i<=ROW;i++)
    {
        for (j=1;j<=COLUMN;j++)
        {
            if (gMaze[i][j]==2) printf("%2c",'>');
            else if(gMaze[i][j]==-1) printf("%2c",'@');
            else printf("%2d",gMaze[i][j]);
        }
        if (i==ROW) printf("--走出\n\n");
        else printf("\n\n");
    }
}
/* 算法描述:  采用了一个通道队列.
 *      首先, 入口入队列,
 *      然后  循环执行 
 *           从队列尾部取出一个点, 把它周围的通道
 *           最多三个,最少0个继续放入到队列头部,然后循环处理尾部点.
 *           这样处理结果是,当iQueuetail 追上iQueueHead 时,表示搜索结束,没有路径.
 *           或者iQueueHead 找到了出口,根据其前趋,形成路径,输出结果,
 *           找到结果后,可以停止搜索,或继续搜索.
 *      这属于一种宽度优先的搜索算法.
 */
int main(void)
{
    int i,j,k,newi,newj;
    int Gotit=0;
    int iQueueTail=0;
	int iQueueHead=1; //ensure gFoots[0] is 0
    //入口入队列(1,1)
    gFoots[iQueueHead].x=1;gFoots[iQueueHead].y=1;gFoots[iQueueHead].pre=0; 
    gMaze[1][1]=-1; //代表(1,1)已经搜索过
    do {
    /* 下一步出队列, 从队列中取出一个通道点.
     * iQueueTail 跟随iQueueHead的脚步,在其基础上继续搜索.
     * 直到找到出口.
     */
        iQueueTail++; //尾索引加1,处理下一个结点
        i=gFoots[iQueueTail].x; j=gFoots[iQueueTail].y; 
        if(i==15&& j==21)
        {
            printf("%d,%d\n",i,j); // for debug
        }

        for (k=0;k<4;k++){         /*沿4个方向搜索*/
            newi=i+gDirect[k].i; newj=j+gDirect[k].j;  /*确定新的搜索位置 */
            /*如果新位置是未搜索通道,则将新位置入队列
             * 如果是墙,继续搜索其它.
             * 如果曾经搜索过,也继续搜索其它,防止回退.
             * */
            if (!gMaze[newi][newj]) {          
                iQueueHead++; //头索引加1
                gFoots[iQueueHead].x=newi; //保存矩阵的x,y坐标值
                gFoots[iQueueHead].y=newj;
                gFoots[iQueueHead].pre=iQueueTail; // 标识新结点的前趋
                gMaze[newi][newj]=-1; /*标识搜索过的位置为-1, 来了就算搜索过*/
            }
            if (newi==ROW && newj==COLUMN){          /*判断是否是出口*/
                print_result(iQueueHead); 
                Gotit=1;
                break; // pay attention, 找到一个出口即可.
            }
        }
    }while(iQueueTail<iQueueHead); // 未搜索完,继续
    if (!Gotit) printf("No Pass!\n");
    return 0;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值