[HDU 1254] 推箱子 解题报告

原题链接

推箱子

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

Problem Description
推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动. 现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.
[HDU 1254] 推箱子 解题报告_第1张图片
 

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
 

/*
HDU 推箱子
精简的解题报告 
此题也真算是双向BFS的一个简单模板了(bfs水题?),要点是如何存储人与箱子当前状态的步数最优解,看见m,n的范围想到用数组大法(四维数组)

总结经验:
1.数据不大时涉及到储存状态的,如发现有DP性质优先考虑状态压缩,如没有DP性质优先考虑数组储存而不是结构体(真的是难以驾驭结构体啊)
2.双向bfs特点:有两个动点相关,且一个点的状态由另一点状态决定,两者具有可变性 
下为模板 
*/
#include 
#include 
#define maxn 10
#define INF 0xfffffff
using namespace std;
//友情提示,bfs的调试难在放置各判断是否压入队列的语句 的 相关位置,发现不了就爆-1,发现了并改正了便可直达病灶 
int n,m,i,j,k,l;//定义能用的全局变量 
int dir[4][2]={0,1,0,-1,-1,0,1,0};//方向 
int vst[maxn][maxn][maxn][maxn];//储存当前状态的step值,并对之后最终的结果作比较得出答案 
int graph[maxn][maxn];//。。。 

struct node{
	int x,y,nx,ny,step;
};

node start;

bool man(node now)//判断人在当前状态下是否满足条件 
{
	return now.x>=0&&now.y>=0&&now.x=0&&now.ny>=0&&now.nx Q;

	Q.push(start);
	vst[start.x][start.y][start.nx][start.ny]=1;//开局的起点一定要定义为可操作的,不然爆-1 (人在起点必然会走一步) 
	while(!Q.empty())
	{
		now=Q.front();
		Q.pop();
		if(graph[now.nx][now.ny]==3)
		{
			ans=min(ans,now.step);//到达终点后决定答案 
		}
		for(i=0;i<4;i++)
		{
			nex=now;
			nex.x+=dir[i][0];
			nex.y+=dir[i][1];
			if(man(nex))
			{
				if(nex.x==nex.nx&&nex.y==nex.ny)//如果箱子与人重合,箱子必往人的行走方向(bfs当前方向)再走一步 
				{
					nex.nx+=dir[i][0];
					nex.ny+=dir[i][1];
					nex.step++;//step++不能放在判断box当前位置是否合法后,因为将不满足bool box()的最后一个判断条件 
					if(box(nex))
					{
						vst[nex.x][nex.y][nex.nx][nex.ny]=nex.step;//更新当前状态的最优解 
						Q.push(nex);
					}
				}else//不重合? 
					{
						vst[nex.x][nex.y][nex.nx][nex.ny]=nex.step;//改变原有vst[当前状态]的INF值,防爆-1,step没有++ 
						Q.push(nex);
					}
			}
		}
	}
	return ans;
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>m>>n;
		for(i=0; i>graph[i][j];
			if(graph[i][j]==4)
			{
				start.x=i;start.y=j;start.step=0;
			}else if(graph[i][j]==2)
			{
				start.nx=i;start.ny=j;
			}
		}
		}
		k=bfs();
		if(k==INF)cout<<-1<

你可能感兴趣的:(C++水题)