Chinaunix首页 | 论坛 | 博客
  • 博客访问: 169642
  • 博文数量: 27
  • 博客积分: 495
  • 博客等级: 下士
  • 技术积分: 299
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-07 19:22
文章分类

全部博文(27)

文章存档

2013年(4)

2012年(1)

2011年(22)

我的朋友

分类: C/C++

2011-10-04 19:37:29

     一个网格迷宫由n行m列的单元格组成,每个大院个要么是空地(用1表示),要么是障碍物(用0表示)。你的任务是找一条从起点到终点的最短移动序列,其中UDLR分别表示往上下左右移动到相邻单元格。任何时候都不能在有障碍物的单元格中,也不能走到迷宫之外。起点和终点保证是空地。n,m<100。
 
的求解方法
 
 
其具体dfs代码为:
int q[MAXN]; 
void bfs(int x,int y)//给的参数是点
{
    int front=0,rear=0,d,u;
    u=x*m+y;     //把点化为坐标存储在m*n的表格中
    vis[x][y]=1; //把点(x,y)置为已经访问     
    fa[x][y]=u;  //把化为编号的号码放在fa数组中存放
    dist[x][y]=0;该数组中存放深度遍历时的遍历号码
    q[rear]=u;  //把编号放在q数组中
    while(front    {
        u=q[front++];  
        x=u/m;
        y=u%m;
        for(d=0;d<4;d++)//这是4个方向的遍历
        {
            int nx=x+dx[d],ny=y+dy[d]; //取到下一个方向
//深度遍历的点的坐标
            if(nx>=0&&nx=0&&ny<=m&&maze[nx][ny]&&!vis[nx][ny])
                {//判断有没有越界 已经被访问 或者是不是不能访问
                    int v=nx*m+ny;//通过新的坐标生成新的编号
                    q[rear++]=v;
                    vis[nx][ny]=1;
                    fa[nx][ny]=u;//存放坐标化为的编码
                    dist[nx][ny]=u;//记下深度遍历时的序号
                    last_dir[nx][ny]=d;//用来保存方向
                }
        }
    }
}
 
 
 
 
这个图表述的是从第一个点扩展开始的顺序和父亲指针
                    这是dist二维数组来盛放的从各个左上角 开始 到达各个格子的最短距离
 
 
fa[][]这个二维数组用来盛放父亲节点的节点序列
这个程序避免了结构体的困扰
而换做  把格子从0开始从上到下编号到-----n*m ,因此i行第j个格子的编号为i*m+j,而编号为u的行号为u/m,列号为u%m,当格子(x,y)扩展到(nx,ny)后,我们要更新的有
dist[nx][ny]=dist[x][y]+1
还有保存新格子(nx,ny)的父亲编号fa[nx][ny]以及
到这个父亲节点的方向last_dir[nx][ny]
 
 
具体代码如下:
这是一个5*5的缩写
#include
  1. #include<iostream>
  2. #include<queue>
  3. #include<vector>

  4. usingnamespace std;
  5. int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
  6. int maze[5][5];//数据输入地图
  7. int vis[5][5];//记录是否访问过
  8. int dist[5][5];//记录每一个点到起点的最近距离
  9. void bfs(int x,int y){
  10.     queue<int>q;//BFS搜索用队列实现
  11.     int d,u=0;
  12.     vis[x][y]=1; q.push(u); while(q.size()!=0){
  13.         u=q.front();//u和下面的临时变量v的作用是将二维图转化为一维数列存储
  14.                    //该方法可以避开另建立结构体记录横坐标值和纵坐标值
  15.                    //例如u=20即代表着第四行(从零算起)第零列的位置
  16.                    //其中转化方法为下面两句
  17.         q.pop();//从队头拿出一个数
  18.         x=u/5; //除以列数,及得到第几行
  19.         y=u%5; //对列数取模,记得到列数
  20.         for(int i=0;i<4;i++){//上下左右查找
  21.             int nx = x+dir[i][0],
  22.                 ny = y+dir[i][1];
  23.             if(nx>=0&&nx<=4&&ny>=0&&ny<=4&&!maze[nx][ny]&&!vis[nx][ny]){
  24.                 int v = nx*5+ny;
  25.                 q.push(v);//加入队尾
  26.                 vis[nx][ny]=1;
  27.                 dist[nx][ny]=dist[x][y]+1;
  28.             }
  29.         }
  30.     }
  31. }
  32. //得到最近矩阵列后,再从终点到起始查找输出
  33. void print(){
  34.     vector<int>arr;
  35.     arr.push_back(24);
  36.     int location=24;
  37.     int temp=dist[4][4]-1;
  38.     while(temp>=0){
  39.         int x=location/5,
  40.             y=location%5;
  41.         int nx,ny;
  42.         for(int i=0;i<4;i++){
  43.                 nx=x+dir[i][0],
  44.                 ny=y+dir[i][1];
  45.             if(nx>=0&&nx<=4&&ny>=0&&ny<=4&&dist[nx][ny]==temp)
  46.                 break;
  47.         }
  48.         location=nx*5+ny;
  49.         arr.push_back(location);
  50.         temp--;//题目说有唯一解,那么如果右下角的数值为8,那么路径必须在dist矩阵中是
  51.               //7,6,5,4....1,0,以此可以找到路径。
  52.     }
  53.     cout<<"(0, 0)"<<endl;
  54.     for(int i=arr.size()-2;i>=0;i--){
  55.         cout<<"("<<arr[i]/5<<", "<<arr[i]%5<<")"<<endl;
  56.     }
  57. }


  58. int main(){
  59.     int i,j;
  60.     memset(vis,0,sizeof(vis));
  61.     memset(dist,0,sizeof(dist));
  62.     for(i=0;i<5;i++)
  63.         for(j=0;j<5;j++)
  64.             cin>>maze[i][j];
  65.     bfs(0,0);
  66.    //输出dist矩阵检验输出
  67.    //因为dist矩阵是print()的基础
  68. /* for(i=0;i<5;i++){
  69.         for(j=0;j<5;j++)cout<<dist[i][j]<<" ";
  70.         cout<<endl;
  71.     }
  72. */
  73.     print();
  74.     return0;
  75. }
  76. //测试数据
  77. /*
  78. 0 1 0 0 0
  79. 0 1 0 1 0
  80. 0 0 0 0 0
  81. 0 1 1 1 0
  82. 0 0 0 1 0
阅读(11738) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~