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. Luogu P2612 [ZJOI2012]波浪

    题目 我们考虑从\(1\)到\(n\)把每个数放到序列里面去,以消掉绝对值. 在最后的序列中,如果\(i\)的某一边是序列的边界,那么\(i\)会产生\(0\)的贡献.如果\(i\)的某一边是一个比\ ...

  2. SCUT - 492 - 鬼符「搦手的鬼畜生」 - 简单数学

    https://scut.online/p/492 求[1,a]范围内的a模m的逆元的数量. 一开始用扩展欧几里得算法草了一发,WA了,当时不太清楚模非质数的周期,看来扩展欧几里得算法的笔记才知道要加 ...

  3. phpstudy配置多站点

    1.打开vhosts.conf文件     目录 Apache/conf/vhosts.conf #开启apache的vhost模块 (此模块默认是关闭的,去掉前面的#号) LoadModule vh ...

  4. vuex的简单理解

    初次接触vuex,谈谈我自己的理解.有待后期改进 首先要知道,Vuex 是专门为 Vue.js 设计的状态管理库.我们知道在用vue.js进行前端项目开发时,会出现很多组件相互之间调用属性.状态,小项 ...

  5. 十三、LaTex中的参考文献BibTex

    将默认文献工具设置为bibtex

  6. django笔记二之数据库

    django笔记二之数据库 [同步数据库之前的操作] yum install MySQL-python.x86_64 -y 2)开启数据库服务并创建表 创建数据库设置 为utf8: create da ...

  7. Codeforces 899 1-N两非空集合最小差 末尾最多9对数计算 pair/链表加优先队列最少次数清空

    A /*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_bac ...

  8. centos7使用cron任务的相关命令(与centos6有区别)

    一.cron任务的自启动相关命令 1.检测cron定时服务是否自启用 systemctl is-enabled crond.service 结果展示如下: enable表示已启用自启动 disable ...

  9. GitHub上一些有趣的开源项目[持续更新]

    TheAlgorithms/C-Plus-Plus 用C++实现了常见的算法,如排序算法,查找算法,以及一些常见的数据数据结构,如链表,二叉树. 链接:https://github.com/TheAl ...

  10. 浅谈MySQL存储引擎选择 InnoDB还是MyISAM

    如果是一些小型的应用或项目,那么MyISAM 也许会更适合.当然,在大型的环境下使用MyISAM 也会有很大成功的时候,但却不总是这样的.如果你正在计划使用一个超大数据量的项目,那么你应该直接使用In ...