• HDU 1254 推箱子(BFS加优先队列)


    传送门:

    http://acm.hdu.edu.cn/showproblem.php?pid=1254

    推箱子

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 9942    Accepted Submission(s): 2920


    Problem Description
    推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动.

    现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.

     
    Input
    输入数据的第一行是一个整数T(1<=T<=20),代表测试数据的数量.然后是T组测试数据,每组测试数据的第一行是两个正整数M,N(2<=M,N<=7),代表房间的大小,然后是一个M行N列的矩阵,代表房间的布局,其中0代表空的地板,1代表墙,2代表箱子的起始位置,3代表箱子要被推去的位置,4代表搬运工的起始位置.
     
    Output
    对于每组测试数据,输出搬运工最少需要推动箱子多少格才能帮箱子推到指定位置,如果不能推到指定位置则输出-1.
     
    Sample Input
    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
     
    Sample Output
    4
     
    Author
    Ignatius.L & weigang Lee
     
    Recommend
    Ignatius.L   |   We have carefully selected several similar problems for you:  1253 1072 1240 1372 1429 
     
     
    分析:
    BFS加优先队列

    从人为起点开始bfs,如果人走的下一步是箱子所在的坐标,说明找到了箱子,

    箱子的坐标为当前所搜方向上人的坐标前进一格(就是推一格箱子,箱子前进的方向和人前进的方向是一致的),

    判断箱子是否到达了目的地,如果是则输出箱子移动的最少步数,到不了就输出-1。

    应该按照所走步数多少决定出队列顺序,所以用优先队列处理下。

    (人从起点找箱子是不计数的)

    需要注意的地方:

    1.要判断人的位置是不是合法:有没有越界或者该位置是墙

    2.要判断能不能推箱子:也就是人有没有找到箱子,比较一开始人和箱子是由距离的,

    如果人走的下一步是箱子所在的坐标,说明找到了箱子

    3.要判断箱子位置的合法性:越界或者该点是墙

    具有做法:

    先将箱子位置和人位置入队

    1.如果箱子到了指定位置,直接输出步数

    2.四个方向搜,先判断人的下一步位置是否合法,合法的话让人一直走,走到人能推箱子的时候

    ,在判断推导箱子之后箱子的位置合不合法,合法的话步数加1

    具体请参考代码:

    code:

    #include<bits/stdc++.h>
    using namespace std;
    int dir[4][2]= {0,1,1,0,0,-1,-1,0}; //方向数组
    #define max_v 12
    int n,m;
    int G[max_v][max_v];//存图
    int vis[max_v][max_v][max_v][max_v];
    struct node
    {
        int x,y;//人的坐标
        int bx,by;//箱子的坐标
        int step;//推箱子的步数
        bool friend operator<(const node &a, const node &b)
        {
            //必须优先队列,步数小优先ye1js
            return a.step>b.step;
        }
    
    } start; //起点
    bool check_person(node next)//判断人的位置是否合法
    {
        if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m&&G[next.x][next.y]!=1)//没有越界且不是墙
            return true;
        else
            return false;
    }
    bool check_box1(node next,node t)//判断能不能推箱子
    {
        if(next.x==t.bx&&next.y==t.by)//如果人走的下一步是箱子所在的坐标,说明找到了箱子
            return true;
        else
            return false;
    }
    int check_box2(int tbx,int tby)//判断箱子坐标的合法性
    {
        if(tbx>=1&&tbx<=n&&tby>=1&&tby<=m&&G[tbx][tby]!=1)//越界或者墙
            return true;
        else
            return false;
    }
    void bfs()
    {
        node next,t;
        priority_queue<node>q;
        memset(vis,0,sizeof(vis));//标志位置空
        //队列初始化
        vis[start.x][start.y][start.bx][start.by]=1;
        start.step=0;
        q.push(start);
    
        while(!q.empty())
        {
            t=q.top();
            q.pop();
            if(G[t.bx][t.by]==3)//箱子到了指定位置
            {
                cout<<t.step<<endl;
                return ;
            }
    
            for(int i=0; i<4; i++)
            {
                next.x=t.x+dir[i][0];//人的下一步
                next.y=t.y+dir[i][1];
    
    
                if(check_person(next))//判断人的下一步位置是否合法
                {
                    next.bx=t.bx;//不能推箱子时,箱子的坐标
                    next.by=t.by;
                    next.step=t.step;
    
    
                    if(check_box1(next,t))//能推箱子
                    {
                        int tbx=t.bx+dir[i][0];//推动箱子之后,箱子的坐标
                        int tby=t.by+dir[i][1];
    
    
                        if(check_box2(tbx,tby))//判断推导箱子之后箱子坐标的合法性,合法则更新坐标
                        {
                            next.bx=tbx;
                            next.by=tby;
                            next.step++;//步数加1
                        }
                    }
                    if(vis[next.x][next.y][next.bx][next.by]==0)//该情况没有搜过,则入队,开始搜
                    {
                        vis[next.x][next.y][next.bx][next.by]=1;
                        q.push(next);
                    }
                }
            }
        }
        cout<<"-1"<<endl;
        return ;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            cin>>n>>m;
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=m; j++)
                {
                    cin>>G[i][j];
                    if(G[i][j]==4)
                    {
                        start.x=i;//找到人在坐标
                        start.y=j;
                        G[i][j]=0;
                    }
                    if(G[i][j]==2)
                    {
                        start.bx=i;//找到箱子的坐标
                        start.by=j;
                        G[i][j]=0;
                    }
                }
            }
            bfs();
        }
        return 0;
    }
  • 相关阅读:
    ModelForm中手动给某些字段赋值
    Ubuntu 18.04.4 LTS 安装Torch步骤
    High-Resolution Image Inpainting using Multi-Scale Neural Patch Synthesis
    Semantic Image Inpainting with Deep Generative Models
    Context Encoders: Feature Learning by Inpainting
    Focus Manipulation Detection via Photometric Histogram Analysis
    Learning to Detect Fake Face Images in the Wild
    A general approach to detect tampered and generated image
    Image splicing forgery detection combining coarse to refined convolutional neural network and adaptive clustering
    Detecting GAN-generated Imagery using Color Cues
  • 原文地址:https://www.cnblogs.com/yinbiao/p/9350249.html
Copyright © 2020-2023  润新知