HDU-1254,BFS+DFS坑题

推箱子

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


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计算箱子到目的地的最短的距离,然后用DFS算出人能不能到箱子之前的状态(这里也可以用BFS计算,数据比较小,才7),因为要这样才可以推动箱子

如果人到不了,那么就continue;掉,因为走不过去

一开始我们要用一个数组来储存人和箱子的坐标,因为人和箱子可以重复走一条路,如果坐标都重复的话说明已经走过了之前的路,就不用再走了

代码:

#include 
#include 
#include 
#include 
using namespace std;
const int maxn=10;
int map[maxn][maxn];
int n,m,dir[4][2]={0,1,0,-1,1,0,-1,0};
int bx,by,px,py,flag;
bool vis[maxn][maxn][maxn][maxn],dfs_vis[maxn][maxn];    //这里四维数组储存箱子和人所在的坐标
struct node
{
    int bx,by;
    int px,py,t;
};
bool judge(int x,int y)                            //判断能不能走
{
    if (x<=0||x>m||y<=0||y>n||map[x][y]==1)
        return true;
    return false;
}
void dfs(int x,int y,int nx,int ny)            //判断人能不能到箱子之前的坐标 nx,ny表示终点
{
    int i;
    if (flag==1)
        return ;
    if (x==nx&&y==ny)
        {
            flag=1;
            return ;
        }
    for (i=0;i<4;i++)
        if (judge(x+dir[i][0],y+dir[i][1])==true||dfs_vis[x+dir[i][0]][y+dir[i][1]]==true)
            continue;
        else 
            {
                dfs_vis[x+dir[i][0]][y+dir[i][1]]=true;                //这里是一个坑点,一开始我按照普通的dfs写,然后....wa了
                dfs(x+dir[i][0],y+dir[i][1],nx,ny);                    //其实走过的路直接标记就可以了,不用恢复,不然会超时的
            }
    return ;
}
int bfs(int x,int y)
{
    int i;
    node now,end;
    now.bx=x;now.by=y;
    now.px=px;now.py=py;now.t=0;
    memset(vis,false,sizeof(vis));
    vis[x][y][px][py]=true;
    queue<node> q;
    while (!q.empty())
        q.pop();
    q.push(now);
    while (!q.empty())
        {
            now=q.front();
            q.pop();
            for (i=0;i<4;i++)
                {
                    end.bx=now.bx+dir[i][0];
                    end.by=now.by+dir[i][1];
                    if (judge(end.bx,end.by)==true)                    //判断箱子能不能走
                        continue;
                    if (vis[end.bx][end.by][now.bx][now.by]==true)
                        continue;
                    memset(dfs_vis,false,sizeof(dfs_vis));
                    dfs_vis[now.bx][now.by]=true;flag=0;                    //这里标记是因为  人推箱子,箱子之前的坐标不能去
                    dfs(now.px,now.py,now.bx-dir[i][0],now.by-dir[i][1]);       //初始地方 
                    if (flag==0)
                        continue;
                    end.px=now.bx;
                    end.py=now.by;
                    end.t=now.t+1;
                    vis[end.bx][end.by][end.px][end.py]=true;
                    if (map[end.bx][end.by]==3)
                        return end.t;
                    q.push(end);
                }
        }
    return -1;
}
int main()
{
    int t,i,j,ans;
    cin>>t;
    while (t--)
        {
            cin>>m>>n;
            for (i=1;i<=m;i++)
                for (j=1;j<=n;j++)
                    {
                        cin>>map[i][j];
                        if (map[i][j]==2)
                            {
                                bx=i;by=j;
                            }
                        if (map[i][j]==4)
                            {
                                px=i;py=j;
                            }
                    }
            ans=bfs(bx,by);
            cout<<ans<<endl;
        }
    return 0;
}

你可能感兴趣的:(BFS,DFS)