zoukankan      html  css  js  c++  java
  • hdu 1254 需注意的地方 果枫

    题意:如题所说。

    注意:1.要考虑人是否能走到推箱子的地方
            2.箱子经过的格子可以再次经过,而箱子经过同一个格子从同一个方向来的只能有一次
            3.人不能穿过箱子

    解法:BFS+BFS

    AC代码:

    View Code
    //bfs+bfs
    #include<iostream>
    #include<queue>
    using namespace std;
    
    #define mem(x,y) memset(x,y,sizeof(x));//牛b的数组初始化,网上学的
    const int M=25;
    int useb[M][M][4],used[M][M];//用作标记useb[][][]之所以是三维数组是因为不单单要标记这一点而是要标记在这点上的方向
    int map[M][M];//地图
    int n,m;//输入地图的行和列
    int bx,by,gx,gy,px,py;// bx,by箱子的坐标  gx,gy目的地的坐标  px,py人的坐标
    int nn[4][2]={{0,1},{-1,0},{0,-1},{1,0}};//方向向量:左,上,右,下
    int foat;//深搜时用作判断是否能找到该点
    
    struct node//节点
    {
        int bx,by;
        int px,py;
        int step;
    
        node(int x,int y,int a,int b,int s)//初始化节点
        {
            bx=x,by=y,px=a,py=b,step=s;
        }
    
        const bool operator <(const node &d)//主要作用是用于队列中的元素按step的升序排列
        {
            return step>d.step;
        }
    };
    
    
    bool outside(int x,int y)//判断是否出界
    {
        if(x>0&&x<=n&&y>0&&y<=m&&map[x][y]!=1)
            return 0;
        else 
            return 1;
    }
    
    
    
    //void dfs(int sx,int sy,int ex,int ey)//悲剧用深搜超时了
    //{
    // if(sx==ex&&sy==ey)
    // {
    //  foat=1;
    //  return ;
    // }
    // for(int i=0;i<4;i++)
    // {
    //  int x=sx+nn[i][0];
    //  int y=sy+nn[i][1];
    //  if(map[x][y]==1||used[x][y]==1||outside(x,y))
    //   continue;
    //  else
    //  {
    //   used[x][y]=1;
    //   dfs(x,y,ex,ey);
    //   used[x][y]=0;
    //  }
    // }
    //}
    
    
    int dfs ( int sx, int sy, int ex, int ey ) //搜索人能否从一点移动到另一点
    {  
        if ( sx == ex && sy == ey ) 
            return 1;
        queue < int > q;
        /*int hh[11][11]; */
        mem(used,0);
        //hh[sx][sy] = 1;
        used[sx][sy]=1;
        q.push ( sx ), q.push ( sy );
        while ( q.size () ) 
        {
            int x = q.front (); 
            q.pop ();
            int y = q.front (); 
            q.pop ();
            for ( int i = 0; i < 4; ++ i ) 
            {
                int xx = x+nn[i][0], yy = y+nn[i][1];
                if ( outside ( xx, yy ) ) 
                    continue;
                if ( !used[xx][yy] ) 
                {
                    if ( xx == ex && yy == ey ) 
                        return 1;
                    q.push ( xx ); 
                    q.push ( yy );
                    used[xx][yy] = 1;
                }
            }
        }
        return 0;
    }
    
    
    
    
    int bfs()
    {
        queue<node>q;
        q.push(node(bx,by,px,py,0));
        while(!q.empty())
        {
            node temp=q.front();
            q.pop();
            if(temp.bx==gx&&temp.by==gy)
                return temp.step;
            for(int i=0;i<4;i++)//i<4是因为有四个方向,每一个方向都要判断是否能进队列
            {
                bx=temp.bx+nn[i][0];
                by=temp.by+nn[i][1];
                px=temp.bx-nn[i][0];
                py=temp.by-nn[i][1];
    
                if(outside(bx,by)||outside(px,py)||useb[bx][by][i])//判断是否出界,或在这个方向上走过
                    continue;
    
                map[temp.bx][temp.by]=1;//防止人穿过箱子当前所在的位置
    
                mem(used,0);
                /*foat=0;*/
                if(!dfs(temp.px,temp.py,px,py))//判断人是否能从原来的点移动到所需的点
                {
                    map[temp.bx][temp.by]=0;//即使不能到达,也必须还原标记
                    continue;
                }
                map[temp.bx][temp.by]=0;//能到达还原标记
    
                if(bx==gx&&by==gy)//找到
                    return  temp.step+1;
    
                q.push(node(bx,by,temp.bx,temp.by,temp.step+1));
                useb[bx][by][i]=1;
            }
        }
        return -1;
    }
    
    
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            map[1][1]=1;
            mem(useb,0);
            mem(map,0);
            int i,j;
            cin>>n>>m;
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=m;j++)
                {
                    cin>>map[i][j];
                    switch(map[i][j])
                    {
                    case 2:bx=i,by=j;break;
                    case 3:gx=i,gy=j;break;
                    case 4:px=i,py=j;break;
                    }
                }
            }
            cout<<bfs()<<endl;
        }
        return 0;
    }
    /*
    
    5 6
    0 0 0 0 0 3
    1 0 1 4 0 1
    0 0 1 0 0 1
    1 0 2 0 0 1
    0 0 0 0 0 1
    
    5 5
    0 3 0 0 0
    1 0 1 4 0
    0 0 1 0 0
    1 0 2 0 0
    0 0 0 0 0
    */

     


     

  • 相关阅读:
    76. 最小覆盖子串 (JAVA)
    95. 不同的二叉搜索树 II (Java)
    HTTP/HTTPS协议 & GraphQL(非RESTFUL方式)
    Round Robin
    94. Binary Tree Inorder Traversal (Java)
    90. Subsets II (Java)
    Notepad++ 连接 FTP 实现编辑 Linux文件
    Git
    根据进程ID查找运行程序目录
    Flink 的广播变量
  • 原文地址:https://www.cnblogs.com/zgfailmr/p/2672029.html
Copyright © 2011-2022 走看看