HDU-1254 java 实现 bfs+bfs,方向剪枝

推箱子

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


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

15 50 3 0 0 01 0 1 4 00 0 1 0 01 0 2 0 00 0 0 0 0
 

Sample Output

4

 


思路:

如果这个箱子不用人来移动,自己就可以移动,那么这道题就是一个最简单的bfs题。但是这道题的问题在于箱子需要人来推,而人不一定能够到达推箱子的位置。那么我们需要另外写一个bfs,来判断当前情况中,人能不能到达这个位置。这个bfs形式上是很简单的,没有多余条件,只需要传入路径,起始位置,结束位置,然后每个位置不能到两次,简单剪个枝,返回true or false 就行了。但是接下来又有一个问题:路径是会改变的。每次移动箱子,人的位置会变,路径也会变。那么相当于人和路径都是跟着箱子走的,是箱子的一个属性。同样的要写进Node类里,跟着Node对象走。最后就是箱子是可以到同一个位置两次的。但是如果你就直接四个方向什么都不管地搜索,这样是要超时的。解决办法就是vis的三维数组记录,同样的方向不能到达两次,这样来剪枝。
代码:


import java.util.LinkedList;  
import java.util.Queue;
import java.util.Scanner;
public class Main {
     static int[][] road;
     static boolean[][][] vis;
     static boolean[][] visman;
     static int[][] dir={{0,1},{1,0},{0,-1},{-1,0}}; //第一组是向右,二是向下,三是向左,四是向上
     static Node start;
     static Node end;
     static man man123;
     static int M,N;
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
      Scanner cin=new Scanner(System.in);
      int T=cin.nextInt();
      while(T-->0)
      {
    	  M=cin.nextInt();
    	  N=cin.nextInt();
    	  road=new int[M][N];
    	  vis=new boolean[M][N][4] ;
    	  for(int i=0;i queue=new LinkedList();
		queue.add(start);
		while(!queue.isEmpty())
		{
			Node node=queue.poll();
			if(node.x==end.x&&node.y==end.y)return node.number;
			vis[node.x][node.y][node.direct]=true;
			for(int i=0;i<4;i++)
			{
			  	 visman=new boolean[M][N];
				 int new_row=node.x+dir[i][0];
				 int new_col=node.y+dir[i][1];
				 if(new_row<0||new_col<0||new_row>=M||new_col>=N||vis[new_row][new_col][i]==true)continue;
				 if(i==0||i==2)
				 {
					 int yy=node.y-dir[i][1];    
					 if(yy<0||yy>=N)continue; //箱子两边都要有位置,为防止数组越界,先判断有没有位置,再判断是不是墙
					 else 
					 if(road[node.x][node.y+dir[i][1]]==1||road[node.x][node.y-dir[i][1]]==1)continue;
				 }
				 if(i==1||i==3)
				 {
					 int xx=node.x-dir[i][0];
					 if(xx<0||xx>=M)continue;
					 else
					 if(road[node.x+dir[i][0]][node.y]==1||road[node.x-dir[i][0]][node.y]==1)continue;
				 }
	             if(i==0||i==2)
	             {
	             	 
	            	 if(bfsman(node.roadd,node.mann,new man(node.x,node.y-dir[i][1]))){
				    	  Node nn=new Node(new_row,new_col,node.number+1,i);
				    	  for(int m=0;m queue=new LinkedList();
		queue.add(start);
		while(!queue.isEmpty())
		{
			man node=queue.poll();
			visman[node.x][node.y]=true;
			if(node.x==end.x&&node.y==end.y)return true;
			for(int i=0;i<4;i++)
			{
				int row=node.x+dir[i][0];
				int col=node.y+dir[i][1];
				if(row<0||col<0||row>=M||col>=N||road[row][col]==2||road[row][col]==1||visman[row][col]==true)continue;
				man nn=new man(row,col);
				queue.offer(nn);
			}
		}
		return false;
	}
	
	static class Node
	{
		int x;
		int y;
		int number;
		int[][] roadd=new int[M][N];
		man mann=new man();
		int direct=-1;
		Node(int xx,int yy,int num,int dd)
		{
			x=xx;
			y=yy;
			number=num; 
			for(int i=0;i




你可能感兴趣的:(HDU-搜索)