推箱子
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6522 Accepted Submission(s): 1857
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
本题应该是我目前做过的最复杂的一到搜索题了
【题意】:就是推箱子,让你求出将箱子推到目的地的最短的次数
【思路】:因为搜索的是最短的路,所以BFS比较合适,在推动箱子的过程中,还要判断是否能走到箱子的被推的那个发力的位置
【坑点&&tricky】:将n放在main里面了,一直没查出来,找了半天。。。。。。
另外,我的BFS太弱了,更喜欢用DFS,今后多练练BFS
【代码】:
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<set>
#include<vector>
#define F first
#define S second
#define PI acos(-1.0)
#define E exp(1.0)
#define INF 0xFFFFFFF
#define MAX -INF
#define len(a) (__int64)strlen(a)
#define mem0(a) (memset(a,0,sizeof(a)))
#define mem1(a) (memset(a,-1,sizeof(a)))
using namespace std;
template<class T> T gcd(T a, T b) {
return b ? gcd(b, a % b) : a;
}
template<class T> T lcm(T a, T b) {
return a / gcd(a, b) * b;
}
template<class T> inline T Min(T a, T b) {
return a < b ? a : b;
}
template<class T> inline T Max(T a, T b) {
return a > b ? a : b;
}
struct node {
int bx, by;
int mx, my;
int step;
};
int mp[10][10];
int has[10][10][10][10];
int dx[] = { 1, -1, 0, 0 };
int dy[] = { 0, 0, 1, -1 };
int f;
int ff[10][10];
int n, m;
int Bx, By, Mx, My;
int Nx, Ny;
int judge(int x, int y) //位置的合法性判断
{
if (x >= 0 && x < n && y >= 0 && y < m && mp[x][y] != 1)
return 1;
return 0;
}
void dfs(int Nx, int Ny, int Mx, int My) { //用DFS来判断是否人能走到那个点
if (Mx == Nx && My == Ny) {
f = 1;
return;
}
for (int i = 0; i < 4 && !f; i++) {
int tx = Nx + dx[i];
int ty = Ny + dy[i];
if (judge(tx, ty) && !ff[tx][ty]) {
ff[tx][ty] = 1;
dfs(tx, ty, Mx, My); //不用回溯,只需判断即可,否则TLE
}
}
}
void bfs(int Bx, int By, int Mx, int My) { //用BFS来推动箱子
queue<node> q;
node p, qq;
p.bx = Bx;
p.by = By;
p.mx = Mx;
p.my = My;
p.step = 0;
q.push(p);
while (!q.empty()) {
p = q.front();
q.pop();
if (mp[p.bx][p.by] == 3) {
printf("%d\n", p.step);
return;
}
for (int i = 0; i < 4; i++) {
qq = p;
qq.bx += dx[i];
qq.by += dy[i];
Nx = p.bx - dx[i];
Ny = p.by - dy[i];
if (judge(qq.bx, qq.by) && judge(Nx, Ny)
&& has[qq.bx][qq.by][Nx][Ny] == 0) {
f = 0;
mem0(ff);
ff[p.bx][p.by] = 1;
ff[Nx][Ny] = 1;
dfs(Nx, Ny, p.mx, p.my);
if (f) {
has[qq.bx][qq.by][Nx][Ny] = 1;
qq.step++;
qq.mx = Nx;
qq.my = Ny;
q.push(qq);
}
}
}
}
printf("-1\n");
return;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int T;
scanf("%d", &T);
while (T--) {
mem0(has);
mem0(mp);
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%d", &mp[i][j]);
if (mp[i][j] == 2) {
Bx = i, By = j;
}
if (mp[i][j] == 4) {
Mx = i, My = j;
}
}
}
bfs(Bx, By, Mx, My);
}
return 0;
}