HDU 1254推箱子(bfs+dfs)

推箱子

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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值