Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 129 Accepted Submission(s): 59

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

思路:

如果没有人,这看箱子的话,这是一个简单的BFS

但是,这道题目另一个限制因素:人。有的箱子位置是人推不到的

棕色为箱子,黑色为墙,蓝色为人,这种情况下箱子就不能往上去

所以我们在BFS箱子位置的同时,也要搜索人的位置(能否到达箱子的相反位置),这里我用的DFS写的

有一个需要注意的点:

箱子可以走回头路

例如如下样例:

5 5
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 1 2 1 1
4 0 3 0 0

若直接去掉标记数组当然可以解决,但这样的话铁定超时

另一个方法是使用一个三维的标记数组,分别记录箱子的位置与人的位置

代码如下:

#include<bits/stdc++.h>
using namespace std;
int m[10][10];
bool vis[10][10][4];
bool vi[10][10];
int M,N;
int endx,endy;
int dfsx,dfsy;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
int to[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct node
{
int x1,y1;//箱子所在位置
int x2,y2;//人所在位置
int step;
void print(){
cout<<"step:"<<step<<" "<<x1+1<<" "<<y1+1<<" "<<x2+1<<" "<<y2+1<<endl;
}
};
int DFS(int rx,int ry)
{
if(rx==dfsx&&ry==dfsy) {
return 1;
}
vi[rx][ry]=1;
for(int i=0;i<4;i++){
int xx=rx+dir[i][0];int yy=ry+dir[i][1];
if(xx<0||xx>=M||yy<0||yy>=N||m[xx][yy]!=0||vi[xx][yy]) continue;
if(DFS(xx,yy)) {
return 1;
}
}
    return 0;
}
queue<node> q;
int BFS(node b)
{
memset(vis,0,sizeof(vis));
while(!q.empty()){
q.pop();
}
q.push(b);
node tmp,t;
while(!q.empty()){
t=q.front();
q.pop();
//cout<<"out"<<" ";t.print();
if(t.x1==endx&&t.y1==endy) return t.step;
for(int i=0;i<4;i++){
tmp=t;
tmp.step++;
tmp.x1+=dir[i][0];
tmp.y1+=dir[i][1];
if(vis[t.x1][t.y1][i]==0&&tmp.x1>=0&&tmp.x1<M&&tmp.y1>=0&&tmp.y1<N&&m[tmp.x1][tmp.y1]==0){
memset(vi,0,sizeof(vi));
vi[tmp.x2][tmp.y2]=1;
dfsx=t.x1+to[i][0];dfsy=t.y1+to[i][1];
m[t.x1][t.y1]=2;
if(DFS(t.x2,t.y2)){
vis[t.x1][t.y1][i]=1;
tmp.x2=t.x1,tmp.y2=t.y1;
q.push(tmp);
//cout<<q.size()<<" "<<"in"<<" ";tmp.print();
}
m[t.x1][t.y1]=0;
}
}
}
return -1;
}
int main()
{
//freopen("data.in","r",stdin);
int t;
//cin>>t;
scanf("%d",&t);
int x,y;
while(t--){
memset(m,-1,sizeof(m));
//cin>>M>>N;
scanf("%d%d",&M,&N);
for(int i=0;i<M;i++){
for(int j=0;j<N;j++){
//cin>>m[i][j];
scanf("%d",&m[i][j]);
}
}
node b;
b.step=0;
for(int i=0;i<M;i++){
for(int j=0;j<N;j++){
if(m[i][j]==2) {b.x1=i,b.y1=j;m[i][j]=0;}
if(m[i][j]==4) {b.x2=i,b.y2=j;m[i][j]=0;}
if(m[i][j]==3) {endx=i,endy=j;m[i][j]=0;}
}
}
cout<<BFS(b)<<endl;
}
}

HDU1254--推箱子(BFS+DFS)的更多相关文章

  1. HDU1254:推箱子(bfs+dfs)

    传送门 题意 给出一副图 0.空地1.墙2.箱子3.目的地4.人所在的位置 问最少几步能将箱子推到目的地 分析 这道题难度略大(菜鸡),首先用vis[bx][by][mx][my]记录当箱子(bx,b ...

  2. HDU1254 推箱子(BFS) 2016-07-24 14:24 86人阅读 评论(0) 收藏

    推箱子 Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推 ...

  3. hdu.1254.推箱子(bfs + 优先队列)

    推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  4. HDU 1254 推箱子 BFS

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1254 题目分析: 做这道题,感觉挺简单的,做着做着就错了20次, 我也是醉了, WA到吐的节奏啊! 思 ...

  5. 推箱子 BFS

    [编程题] 推箱子 大家一定玩过“推箱子”这个经典的游戏.具体规则就是在一个N*M的地图上,有1个玩家.1个箱子.1个目的地以及若干障碍,其余是空地.玩家可以往上下左右4个方向移动,但是不能移动出地图 ...

  6. hdu - 1254 推箱子 (bfs+bfs)

    http://acm.hdu.edu.cn/showproblem.php?pid=1254 题目意思很简单,只要思路对就好. 首先考虑搬运工能否到达推箱子的那个点,这个可以根据箱子前进方向得出搬运工 ...

  7. hdu 1254 推箱子(嵌套搜索,bfs中有dfs)

    推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  8. 推箱子 (hdu1254)(bfs双重广搜)

    推箱子 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission ...

  9. HDU 1254 推箱子(BFS)

    Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不 ...

随机推荐

  1. 解决SQLPLUS ??? 显示的临时办法

    错误现象为: 解决命令 export NLS_LANG=american_america.zhs16gbk

  2. set的常见用法

    set的使用 set是什么 set是一个内部有序且不含重复元素的容器 用处 *使得元素自动有序 *去除重复元素 set的引入 # include <set> using namespace ...

  3. Nob常用命令

    说明:此文件为常用的命令笔记 规则: .使用"[组名]"分组,如[linux] .使用"<标题一>"标示知识点,可用"<<二级 ...

  4. python3的base64编解码

    使用python3的base64编解码实现字符串的简易加密解密 引言: 在一些项目中,接口的报文是通过base64加密传输的,所以在进行接口自动化时,需要对所传的参数进行base64编码,对拿到的响应 ...

  5. npm学习(二)之如何防止权限错误

    如何防止权限错误 如果您在尝试全局安装包时看到EACCES错误,请阅读本章.如果更改安装npm的目录,通常可以避免此错误.要做到这一点,要么使用版本管理器重新安装npm(推荐)或手动更改npm的默认目 ...

  6. thinkphp5+layui多图片上传

    准备资料 下载layui <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  7. vue打包时,assets目录 和static目录下文件的处理区别(nodeModule中插件源码修改后,打包后的文件应放在static目录)

    为了回答这个问题,我们首先需要了解Webpack如何处理静态资产.在 *.vue 组件中,所有模板和CSS都会被 vue-html-loader 及 css-loader 解析,并查找资源URL.例如 ...

  8. vue.js(5)--事件修饰符

    vue中的事件修饰符(.stop..prevent..self..capture..once) (1)实例代码 <!DOCTYPE html> <html lang="en ...

  9. DEV第三方控件的GalleryControl控件

    1.获取选中的图片 List<GalleryItem> lstArray = gclImage.Gallery.GetCheckedItems(); 2.滚动到GalleryControl ...

  10. redis常见问题和解决方案

    转载:https://www.cnblogs.com/aspirant/p/6820262.html [原创]那些年用过的Redis集群架构(含面试解析) redis常见问题和解决方案 持久化.主从问 ...