HDU 1254 推箱子

推箱子

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

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
解题思路:BFS套BFS搜索人可以走的位置
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#pragma comment(linker, "/STACK:102400000,102400000")
#define N 10
#define Inf (1<<30)
using namespace std;
int map[N][N],mov[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
bool vis[N][N][N][N][N][N],visit[N][N][N<<5];
int ans;
struct Node
{
    int x,y;
};
struct State
{
    int xm,ym,xb,yb,t;
};
void bfsm(int x0,int y0,int x1,int y1)
{
    int i,j;
    queue<Node> q;
    Node ini;
    for(i=0;i<10;i++)
        for(j=0;j<10;j++)
            vis[i][j][x0][y0][x1][y1]=false;
    ini.x=x0;ini.y=y0;
    q.push(ini);
    vis[x0][y0][x0][y0][x1][y1]=vis[x1][y1][x0][y0][x1][y1]=vis[0][0][x0][y0][x1][y1]=true;
    while(!q.empty())
    {
        ini=q.front();
        q.pop();
        Node tmp;
        for(i=0;i<4;i++)
        {
            tmp=ini;
            tmp.x+=mov[i][0];
            tmp.y+=mov[i][1];
            if(!vis[tmp.x][tmp.y][x0][y0][x1][y1]&&map[tmp.x][tmp.y]!=1&&map[tmp.x][tmp.y]!=-1)
            {
                vis[tmp.x][tmp.y][x0][y0][x1][y1]=true;
                q.push(tmp);
            }
        }
    }
}
int bfsb(int x0,int y0,int x1,int y1,int x2,int y2)
{
    queue<State> q;
    State ini;
    ini.xm=x0;ini.ym=y0;ini.xb=x1;ini.yb=y1;ini.t=0;
    q.push(ini);
    while(!q.empty())
    {
        ini=q.front();
        q.pop();
        if(ini.xb==x2&&ini.yb==y2)
            ans=min(ans,ini.t);
        if(!vis[0][0][ini.xm][ini.ym][ini.xb][ini.yb])
            bfsm(ini.xm,ini.ym,ini.xb,ini.yb);
        for(int i=0;i<4;i++)
        {
            int xt1=ini.xb+mov[(i+2)%4][0];int yt1=ini.yb+mov[(i+2)%4][1];
            int xt2=ini.xb+mov[i][0];int yt2=ini.yb+mov[i][1];
            int t=ini.t+1;
            if(vis[xt1][yt1][ini.xm][ini.ym][ini.xb][ini.yb]&&!visit[xt2][yt2][t]&&map[xt2][yt2]!=1&&map[xt2][yt2]!=-1)
            {
                visit[xt2][yt2][t]=true;
                State tmp;
                tmp.xm=ini.xb;tmp.ym=ini.yb;
                tmp.xb=xt2;tmp.yb=yt2;
                tmp.t=t;
                q.push(tmp);
            }
        }
    }
    return ans==Inf?-1:ans;
}
int main()
{
    int i,j,t,m,n,xr,yr,xb,yb,xe,ye;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&m,&n);
        memset(map,-1,sizeof(map));
        memset(vis,false,sizeof(vis));
        memset(visit,false,sizeof(visit));
        for(i=1;i<=m;i++)
            for(j=1;j<=n;j++)
            {
                scanf("%d",&map[i][j]);
                if(map[i][j]==2)
                    xb=i,yb=j;
                else if(map[i][j]==3)
                    xe=i,ye=j;
                else if(map[i][j]==4)
                    xr=i,yr=j;
            }
        ans=Inf;
        visit[xb][yb][0]=true;
        printf("%d\n",bfsb(xr,yr,xb,yb,xe,ye));
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值