一个迷宫问题

问题:通过计算机程序找出一条离开迷宫的路径。

迷宫表示:我们用一个二维数组来表示迷宫,设该二维数组为maze[i][j],1 <= i <= m并且1 <= j <=p。1表示不能通过的位置,0表示可以从上面通过。

如图所示:

         因为迷宫被表示为一个二维数组,因此无论在任何位置都可以用行数i和列数j来表示。同理当前位置[i][j]的下一个位置也可以用[g][h]来表示。我们首先定义8个方向,分别是N,NE,E,SE,S,SW,W和NW。当前位置与下一步所到的位置关系如图:

这里必须注意,因为不是所有位置都有8个相邻的位置。如果[i][j]在边界上,无论是i = 1或m,或者j = 1或p,那么相邻位置书都小于8,并且可能只有3个相邻位置存在。为了避免考虑边界条件,我们用1将迷宫包围。这事需要maze[m+2][p+2]来声明迷宫,这里我们假设从maze[1][1]进入,maze[m][p]离开。

另一个化简问题的方法是预先把可能的方向定义在表Move中,如图:

数据结构:

enum directions{N,NE,E,SE,S,SW,W,NW};

class offsets //运动方向的类

{

public:

   int a,b;

};

offsets Move[8];

如果我们当前位置[i][j],希望下一步在当前位置的东面位置[g][h],那么进行如下计算:

g = i + Move[E].a;              h = j + Move[E].b;

例如:[3][4],那么东面一个位置就是[4][4]。

Path分析: 当我们在迷宫中行走的时候,可能有多个方向可以前进。所以每到达一个新位置我们要检查可以行走的方向(即下一步maze[g][h] = 0),并且从东开始顺时针方向一一尝试。因为我们并不能预知那个方向更好,所以只能选择一个方向,并把当前位置和上一步的位置保存起来。这样的话,如果选择了一条错误的路线,就可以退回去并且尝试下一个方向。为了防止进入同一条路径两次,我们使用另一个二维数组mark[m+2][p+2],该数组中每个元素一开始都被置为0,一旦到达某位置mark[i][j] = 1 。当前进到[m][p],证明已经找到正确离开迷宫的路径(假设maze[m][p] = 0,否则问题无解)。

代码解决方案:

#include<iostream>
#include<stack>
using namespace std;

const int m = 3;
const int p = 4; 
int maze[m+2][p+2] = {{1,1,1,1,1,1},{1,0,0,1,1,1},{1,1,0,1,1,1},{1,1,1,0,0,1},{1,1,1,1,1,1}};
int mark[m+2][p+2];enum directions{N,NE,E,SE,S,SW,W,NW};

class offsets //运动方向的类
{
public:
  int a,b;
};
offsets Move[8];
void funtion1()
{//初始化 运动方向
  Move[N].a = -1;
  Move[N].b = 0;
  Move[NE].a = -1;
  Move[NE].b = 1;
  Move[E].a = 0;
  Move[E].b = 1;
  Move[SE].a = 1;
  Move[SE].b = 1;
  Move[S].a = 1;
  Move[S].b = 0;
  Move[SW].a = 1;
  Move[SW].b = -1;
  Move[W].a = 0;
  Move[W].b = -1;
  Move[NW].a = -1;
  Move[NW].b = -1;
}
class Items
{
public:
  int x,y,dir;
  Items(int i,int j,int d)
  {
    x = i;
    y = j;
    dir = d;
  }
};

template<class T>
void funtion2(stack<T> &s)
{
  stack<Items> stack;
  while(!s.empty())
  {
    stack.push(s.top());
    s.pop();
  }
  while (!stack.empty())
  {
    Items item = stack.top();
    cout<<item.x<<','<<item.y<<','<<item.dir;
    stack.pop();
    cout<<endl;
  }
}
void Path(int m,int p)
{
//Start at (1,1)
  mark[1][1] = 1;
  stack<Items> stack ;
  Items temp(1,1,N);
  stack.push(temp);
  while(! stack.empty())
  {//stack not empty
    temp = stack.top();
    stack.pop();
    int i = temp.x;
    int j = temp.y;
    int d = temp.dir;
  while(d<8)
  {
    int g = i+Move[d].a;
    int h = i+Move[d].b;
    if(g == m && h ==p )
    {
      funtion2(stack);
      cout<<i<<" "<<j<<endl;
      cout<<m<<" "<<p<<endl;
      return;
    }
    if((!maze[g][h]) && (!mark[g][h]))
    {
      mark[g][h] = 1;
      temp.x = i;
      temp.y = j;
      temp.dir = d+1;
      stack.push(temp);
      i = g;j = h;d = N;
    }
    else
      d++; 

  } 
  }
  cout<<"No path in maze."<<endl;
}

int main()
{
  funtion1();
  Path(m,p);
}

 

 

 

2013/5/22

 

转载于:https://www.cnblogs.com/FlightButterfly/archive/2013/05/22/3093689.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值