zoukankan      html  css  js  c++  java
  • hdu 1254 推箱子(双重bfs)

    题目链接

    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

    分析:
    推箱子的游戏规则就不用多少了把,相信大家都玩过。我们主要的就是根据箱子现在的为止来考虑它下一步能够走到的为止,但是仅仅箱子能够走到这里来是不行的啊,箱子毕竟得有人推着才能往前走,也就意味着在箱子能走到这个位置时,还要判断人能不能够走到对应得位置,这一点是十分关键的。

    用广搜寻找最小步数,但推箱子需要满足以下几个条件:
    1.人能走到推箱子的那个位置
    2.人不能穿过箱子.
    3.箱子可以回到前一状态的位置,但不是同一方向回到的.

    代码:

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include<string.h>
    using namespace std;
    
    const int maxn = 10;
    const int dx[] = {-1,1,0,0};
    const int dy[] = {0,0,-1,1};
    
    struct Node
    {
        int x,y,step;
        Node(int x,int y,int step = -1): x(x), y(y), step(step) {}
    };
    
    int n,m,sx,sy,ex,ey,tmp[maxn][maxn];
    int dist[maxn][maxn][4],px,py;
    bool vis[maxn][maxn];
    
    
    bool bfs1(int x1,int y1,int x2,int y2)
    {
        if(tmp[x1][y1] != 0 || tmp[x2][y2] != 0) return false;
        queue<int> qx,qy;
        qx.push(x1);
        qy.push(y1);
        memset(vis,0,sizeof(vis));
        vis[x1][y1] = true;
        while(!qx.empty())
        {
            int x = qx.front(), y = qy.front();
            qx.pop();
            qy.pop();
            if(x == x2 && y == y2) return true;
            for(int i = 0; i < 4; i++)
            {
                int nx = x + dx[i], ny = y + dy[i];
                if(!vis[nx][ny] && tmp[nx][ny] == 0)
                {
                    qx.push(nx);
                    qy.push(ny);
                    vis[nx][ny] = true;
                }
            }
        }
        return false;
    }
    
    int bfs()
    {
        queue<Node> box,man;
        box.push(Node(sx,sy,0));
        man.push(Node(px,py));
        for(int i = 0; i < 4; i++) dist[sx][sy][i] = -1;
        int x,y,nx,ny,xp,yp,nxp,nyp,pre;
        while(!box.empty())
        {
            Node nowbox = box.front(), nowman = man.front();
            box.pop();
            man.pop();
            x = nowbox.x;
            y = nowbox.y;
            pre = nowbox.step;
            xp = nowman.x;
            yp = nowman.y;
            //printf("box: %d %d  man: %d %d time: %d
    ",x,y,xp,yp,dist[x][y][pre]);
            if(x == ex && y == ey) return dist[x][y][pre] + 1;
            for(int i = 0; i < 4; i++)
            {
                nx = x + dx[i];
                ny = y + dy[i];
                nxp = x - dx[i];
                nyp = y - dy[i];
                tmp[x][y] = 1;
                if((dist[nx][ny][i] == -1 || dist[nx][ny][i] >= dist[x][y][pre] + 1)
                        && tmp[nx][ny] == 0
                        && bfs1(xp,yp,nxp,nyp))
                {
                    dist[nx][ny][i] = dist[x][y][pre] + 1;
                    box.push(Node(nx,ny,i));
                    man.push(Node(x,y));
                }
                tmp[x][y] = 0;
            }
        }
        return -1;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            memset(dist,-1,sizeof(dist));
            memset(tmp,0x3f,sizeof(tmp));
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= m; j++)
                {
                    scanf("%d",&tmp[i][j]);
                    if(tmp[i][j] == 2)//箱子起点
                    {
                        sx = i;
                        sy = j;
                    }
                    if(tmp[i][j] == 3)//箱子终点
                    {
                        ex = i;
                        ey = j;
                    }
                    if(tmp[i][j] == 4)//搬运工位置
                    {
                        px = i;
                        py = j;
                    }
                    if(tmp[i][j] != 1) tmp[i][j] = 0;
                }
            }
            printf("%d
    ",bfs());
        }
        return 0;
    }
    
  • 相关阅读:
    LeetCode中等题(三)
    java之使用poi对excel的.xls和.xlsx访问
    JAVA编程-----------40、字符串排序
    JAVA编程------------38、写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度
    JAVA编程---------37、n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡是报到3的人退出圈子,问最后留下的是原来第几号的那位。
    JAVA编程--------------36、有n个整数,使其前面各数顺序向后移m个位置最后m个数变成前面m个数
    JAVA编程-------------24、将一组数的最大数放在第一位,最小的数放在最后一位
    JAVA编程------------33、打印杨辉三角
    JAVA编程--------------32、取一个整数的4-7位
    JAVA编程---------------31、将一个数组逆序输出
  • 原文地址:https://www.cnblogs.com/cmmdc/p/7611362.html
Copyright © 2011-2022 走看看