迷宫求解

迷宫求解描述:

 

栈的方式——深度优先

算法:

  1. 初始化栈,出发点先入栈
  2. 当栈不空时,出栈顶元素,当前位置不是墙壁并且没走过,标记已走
  3. 把相邻的四个位置压入栈,依次等待搜索
  4. 不断循环2-3,如果已经到达终点,退出循环
#include "stdio.h"
#define StackSize 100


typedef struct{
  int i;
  int j;
} ElemType;

typedef struct {
  ElemType elem[StackSize];
  int top;
}SqStack;

InitStack(SqStack *pS)
{
  pS->top=0; /* top指向栈顶的上一个元素 */
}

int Push(SqStack *pS,ElemType e)
{
  if (pS->top==StackSize-1)   /* 栈满 */
    return 0;

  pS->elem[pS->top]=e;
  pS->top=pS->top+1;
  return 1;
}

int Pop(SqStack *pS,ElemType* pe)
{
  if (pS->top==0)  /* 栈空 */
    return 0;

  pS->top = pS->top - 1;
  *pe = pS->elem[pS->top];
  return 1;
}

main()
{
  SqStack S;
  ElemType e;
  int maze[10][10]={      /* 离散迷宫矩阵,0表示墙壁,1表示可以走的道路 */
    {0,0,0,0,0,0,0,0,0,0},
    {0,1,1,0,1,1,1,0,1,0},
    {0,1,1,0,1,1,1,0,1,0},
    {0,1,1,1,1,0,0,1,1,0},
    {0,1,0,0,0,1,1,1,1,0},
    {0,1,1,1,0,1,1,1,1,0},
    {0,1,0,1,1,1,0,1,1,0},
    {0,1,0,0,0,1,0,0,1,0},
    {0,0,1,1,1,1,1,1,1,0},
    {0,0,0,0,0,0,0,0,0,0}
  };
  int i,j,ti,tj;

  InitStack(&S); /* 初始化栈为空 */

  e.i=1;e.j=1;   /* 搜索的起点位置 */
  Push(&S,e);    /* 把起点位置入栈,准备搜索*/

  while(Pop(&S,&e)){          /* 当栈不空,则出栈并保存到e中 */
    if (maze[e.i][e.j]==1) {  /* 迷宫的当前位置不是墙壁并且没走过 */
      maze[e.i][e.j]=2;       /* 标记已走过 */
      if (e.i==8 && e.j==8)   /* 如果已经到达终点,退出循环 */
        break;
      else {
        /* 把相邻的四个位置压入栈,依次等待搜索,深度优先 */ 
        ti=e.i;  tj=e.j;
        e.i=ti-1; e.j=tj; Push(&S,e);  
        e.i=ti+1; e.j=tj; Push(&S,e);  
        e.i=ti; e.j=tj-1; Push(&S,e);
        e.i=ti; e.j=tj+1; Push(&S,e);  /* 最先搜索:右边位置 */ 
      }
    }
  }


  /* 打印出整个迷宫,2表示搜索过的位置。但是没有显示具体路径 */
  printf("\n\n");
  for(i=0;i<10;i++) {
    for(j=0;j<10;j++)
      printf("%2d ",maze[i][j]);
    printf("\n");
  }

  getch();
}
View Code

另一种写法

#include "stdio.h"
#define StackSize 100

typedef struct{
  int i,j;
}PosType;

typedef struct{
  PosType pos;
  int di;
} ElemType;

typedef struct {
  ElemType elem[StackSize];
  int top;
}SqStack;

InitStack(SqStack *pS)
{
  pS->top=0; /* top指向栈顶的上一个元素 */
}

int Push(SqStack *pS,ElemType e)
{
  if (pS->top==StackSize-1)   /* 栈满 */
    return 0;

  pS->elem[pS->top]=e;
  pS->top=pS->top+1;
  return 1;
}

int Pop(SqStack *pS,ElemType* pe)
{
  if (pS->top==0)  /* 栈空 */
    return 0;

  pS->top = pS->top - 1;
  *pe = pS->elem[pS->top];
  return 1;
}

main()
{
  SqStack S;
  ElemType e;
  PosType pos,pos_end;
  int maze[10][10]={      /* 离散迷宫矩阵,0表示墙壁 */
    {0,0,0,0,0,0,0,0,0,0},
    {0,1,1,0,1,1,1,0,1,0},
    {0,1,1,0,1,1,1,0,1,0},
    {0,1,1,1,1,0,0,1,1,0},
    {0,1,0,0,0,1,1,1,1,0},
    {0,1,1,1,0,1,1,1,1,0},
    {0,1,0,1,1,1,0,1,1,0},
    {0,1,0,0,0,1,0,0,1,0},
    {0,0,1,1,1,1,1,1,1,0},
    {0,0,0,0,0,0,0,0,0,0}
  };
  int i,j;

  InitStack(&S);
  pos_end.i=8;pos_end.j=8;
  pos.i=1;pos.j=1;

  do {
    if (maze[pos.i][pos.j]==1) {  /* 当前位置不是墙壁并且没走过 */
      maze[pos.i][pos.j]=2;   /* 标记已走过 */
      e.pos = pos;
      e.di = 1;
      Push(&S,e);           /* 加入路径 */
      if (pos.i==pos_end.i && pos.j==pos_end.j)     /* 如果已经到达终点,退出循环,求得的路径放在栈中 */
        break;
      else
        pos.j++;            /* 下一个位置是当前位置的右邻 */
    }
    else{  /* 当前位置不能通过 */
      if(S.top>0){
        Pop(&S,&e);
        while(e.di==4 && S.top>0){
          maze[e.pos.i][e.pos.j]=-1;  /* 留下不能通过的标记,并退回一步 */
          Pop(&S,&e);
        }
        if (e.di<4){
          e.di++; Push(&S,e);      /* 换下一个方向搜索 */
          pos.i=e.pos.i; pos.j=e.pos.j;
          if (e.di==2) pos.i++;    /* 设定当前位置是该方向上的相邻块“右下左上” */
          else if (e.di==3) pos.j--;
          else if (e.di==4) pos.i--;
        }
      }
    }
  }while(S.top>0);


  /* 求得的路径放在栈中 */
  printf("\n");
  while(Pop(&S,&e))
    printf("\n(%d,%d)",e.pos.i,e.pos.j);


  /* 打印出整个迷宫,2的是所找到的路径,-1是走过的不通的路径 */
  printf("\n\n");
  for(i=0;i<10;i++) {
    for(j=0;j<10;j++)
      printf("%2d ",maze[i][j]);
    printf("\n");
  }

  getch();
}
View Code

 

队列的方式——广度

#include"stdio.h"
#include"stdlib.h"

#define Maxsize 100

typedef struct{
    int i;
    int j;
    int pre;//记录前一个结点下标
}DataType;//记录位置

typedef struct {
    DataType data[Maxsize];
    int front,rear;
}Queue;
//初始化队列
void InitQueue(Queue *Q)
{
    Q->front=Q->rear=0;
}
//入队
int InQueue(Queue *Q,DataType x)
{
    if((Q->rear+1)%Maxsize==Q->front)
        return 0;
    Q->rear=(Q->rear+1)%Maxsize; //if (Q->rear+1)==Maxsize,Q->rear=0
    Q->data[Q->rear]=x;
    return 1;
}
//判断空队列
int EmptyQueue(Queue *Q)
{
    if(Q->rear==Q->front)
        return 1;
    else
        return 0;
}
//出队
int OutQueue(Queue *Q,DataType *x)
{
    if(EmptyQueue(Q))
        return 0;
    Q->front=(Q->front+1)%Maxsize;
    *x=Q->data[Q->front];
    return 1;
}

void main()
{
    Queue Q;
    DataType x;
    int maze[10][10]={      /* 离散迷宫矩阵,0表示墙壁,1表示可以走的道路 */
        {0,0,0,0,0,0,0,0,0,0},
        {0,1,1,0,1,1,1,0,1,0},
        {0,1,1,0,1,1,1,0,1,0},
        {0,1,1,1,1,0,0,1,1,0},
        {0,1,0,0,0,1,1,1,1,0},
        {0,1,1,1,0,1,1,1,1,0},
        {0,1,0,1,1,1,0,1,1,0},
        {0,1,0,0,0,1,0,0,1,0},
        {0,0,1,1,1,1,1,1,1,0},
        {0,0,0,0,0,0,0,0,0,0}
    };

    InitQueue(&Q);

    int i,j,ti,tj;
    int di;
    x.i=1; x.j=1; //起始位置(1,1)
    x.pre=0;
    
    InQueue(&Q,x);

    while(OutQueue(&Q,&x))
    {
        if(x.i==8&&x.j==8)
            break;
        ti=x.i;  tj=x.j;
        for(di=0;di<4;di++)
        {
            switch(di)
            {
            case 0://
                x.i=ti-1;
                x.j=tj;
                break;
            case 1://
                x.i=ti+1;
                x.j=tj;
                break;
            case 2://
                x.i=ti;
                x.j=tj-1;
                break;
            case 3://
                x.i=ti;
                x.j=tj+1;
                break;
            }
            if(1==maze[x.i][x.j])//如果有路并且没有访问过
            {
                x.pre=Q.front; 
                x.i=x.i;x.j=x.j;
                InQueue(&Q,x);
                maze[x.i][x.j]=2; //表示已经访问过
            }
        }//for
    }
    
    
    printf("\n\n搜索过后的迷宫:\n");
    for(i=0;i<10;i++) 
    {
        for(j=0;j<10;j++)
            printf("%2d ",maze[i][j]);
        printf("\n");
    }
    printf("\n\n所走路线为(最短路线):\n");

//*
    do
    {
        printf("(%d,%d)\t",Q.data[Q.front].i,Q.data[Q.front].j);
        Q.front=Q.data[Q.front].pre;
    }while(Q.front!=0);
    //*/
}
View Code

 

递归的方式——深度优先

#include "stdio.h"
int SearchFun(int maze[][10],int i, int j)
{
    if (maze[i][j]==1) {  /* 迷宫的当前位置不是墙壁并且没走过 */
      maze[i][j]=2;       /* 标记已走过 */
      if (i==8 && j==8)   /* 如果已经到达终点,返回 */
        return 1;
      else {
        /* 依次搜索相邻的四个位置,深度优先 */ 
        if (SearchFun(maze,i,j+1))   /* 最先搜索:右边位置 */
            return 1;
        if (SearchFun(maze,i,j-1))
            return 1;
        if (SearchFun(maze,i+1,j))
            return 1;
        if (SearchFun(maze,i-1,j))
            return 1;
      }
    }
    return 0;
}

main()
{
  int maze[10][10]={      /* 离散迷宫矩阵,0表示墙壁,1表示可以走的道路 */
    {0,0,0,0,0,0,0,0,0,0},
    {0,1,1,0,1,1,1,0,1,0},
    {0,1,1,0,1,1,1,0,1,0},
    {0,1,1,1,1,0,0,1,1,0},
    {0,1,0,0,0,1,1,1,1,0},
    {0,1,1,1,0,1,1,1,1,0},
    {0,1,0,1,1,1,0,1,1,0},
    {0,1,0,0,0,1,0,0,1,0},
    {0,0,1,1,1,1,1,1,1,0},
    {0,0,0,0,0,0,0,0,0,0}
  };
  int i,j;

  SearchFun(maze,1,1);


  /* 打印出整个迷宫,2表示搜索过的位置。但是没有显示具体路径 */
  printf("\n\n");
  for(i=0;i<10;i++) {
    for(j=0;j<10;j++)
      printf("%2d ",maze[i][j]);
    printf("\n");
  }

  getch();
}
View Code

 

posted @ 2019-05-08 21:49  亦海  阅读(230)  评论(0编辑  收藏  举报