杭电1254java实现(双bfs 优先队列)

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

推箱子



推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个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


思路:把问题拆分


1:如果单看箱子的移动,就是一个bfs求最短。


2:但是这里多了条件就是需要人去推,那么在箱子移动就要记录小人移动的位置,小人推箱子前的位置和需要在的位置推箱子,要判断能否到达,这又是一个bfs。要注意小人除了箱子的位置和墙奇特都可以走。要判断小人是否越界,可走。


3:这里的人和箱子的位置是会变的,然而他们的初始位置是标记其他数字不是0,最好将他的数字改成0,使用参数单独标记其位置。


4:人的遍历要记忆一次遍历,因为我要求的只是到达。但是箱子的遍历要记录不是走一次,一个位置可走两次。可能箱子卡在门口推出去,人再内,人在推出去推进来。


5:箱子要用优先队列优化,标记为推得次数。


代码如下:


import java.util.ArrayDeque;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
public class 杭电1254 {
  static int x1,y1,x2,y2,x3,y3,m,n;//人 箱子 结束点
  static int x[]= {0,1,0,-1};
  static int y[]= {1,0,-1,0};
  static int a[][];//存储值
  static boolean jud=false;
   public static void main(String[] args) {
     Scanner sc=new Scanner(System.in);
     int t=sc.nextInt();//测试数据
     for(int t1=0;t1 q2=new PriorityQueue(comepare);//优先队列
       q2.add(new xiang(x2,y2,x1,y1,0));//加入第一个箱子和人的位子
       while(!q2.isEmpty())
       {
         xiang xiang=q2.poll();
         int x4=xiang.xx;int y4=xiang.yx;//箱子
         int x5=xiang.xr;int y5=xiang.yr;//ren
         if(x4==x3&&y4==y3){System.out.println(xiang.time);jud=true;break;}
         else for(int i=0;i<4;i )
         {
           if(x4 x[i]>=0&&x4 x[i]=0&&y4 y[i]=0&&x4-x[i]=0&&y4-y[i]2)//允许它来回一次,也就是这个点可以走两次
                 mark[x4 x[i]][y4 y[i]]=true;
               }
               }
             }
           }
         }
       }
       if(!jud) {System.out.println(-1);}
       jud=false;     
     }
   }
public static boolean move(int x11,int y11,int x21,int y21,int x41,int y41 )//起始点,末尾,箱子
{
  boolean b[][]=new boolean[m][n];
  Queue q1=new ArrayDeque();
  b[x11][y11]=true;//起点和箱子当作遍历过
  b[x41][y41]=true;
  q1.add(new zuobiao(x11,y11)); 
  while(!q1.isEmpty())
  {
    zuobiao zuo=q1.poll();
    int x31=zuo.x;int y31=zuo.y;
    if(x31==x21&&y31==y21){return true;}
    else for(int i=0;i<4;i )
    {
      if(x31 x[i]>=0&&x31 x[i]=0&&y31 y[i]comepare=new Comparator()
{
  public int compare(xiang arg0, xiang arg1) {
    return(int) (arg0.time-arg1.time);
  }};
private  static class xiang
 {
    int xx;
    int yx;//箱子
    int xr;
    int yr;//人
    int time;
    public xiang(int xx,int yx,int xr,int yr,int time)
    {
      this.xx=xx;
      this.yx=yx;
      this.xr=xr;
      this.yr=yr;
      this.time=time;
    }
 }
private static class zuobiao
{
  int x;
  int y;
  public zuobiao(int x,int y)
  {
    this.x=x;
    this.y=y;
  }   
}
}
目录
相关文章
|
8月前
|
Java
【Java每日一题,BFS】Catch That Cow
【Java每日一题,BFS】Catch That Cow
|
3天前
|
Java 开发者
Java一分钟之-高级集合框架:优先队列(PriorityQueue)
【5月更文挑战第18天】`PriorityQueue`是Java集合框架中的无界优先队列,基于堆数据结构实现,保证队头元素总是最小。常见操作包括`add(E e)`、`offer(E e)`、`poll()`和`peek()`。元素排序遵循自然排序或自定义`Comparator`。常见问题包括错误的排序逻辑、可变对象排序属性修改和混淆`poll()`与`peek()`。示例展示了自然排序和使用`Comparator`的排序方式。正确理解和使用`PriorityQueue`能提升应用性能。
36 6
|
8月前
|
Java
【Java每日一题,优先队列简单题】数组修改
【Java每日一题,优先队列简单题】数组修改
|
6天前
|
算法 Java
BFS(广度搜索|宽度搜索)无向图遍历(JAVA手把手深入解析)
BFS(广度搜索|宽度搜索)无向图遍历(JAVA手把手深入解析)
54 0
|
6天前
|
Java 调度
Java优先队列(堆)理解和使用
Java优先队列(堆)理解和使用
48 0
|
Java
Java 实现汉字按照首字母分组排序
Java 实现汉字按照首字母分组排序
574 0
|
11月前
|
Java
数据结构(11)图的遍历,DFS、BFS的JAVA实现
11.1.图的遍历 图的遍历,即将图内所有顶点都访问一遍。 有两种遍历方式: BFS DFS 以下图的遍历为例:
62 0
|
11月前
|
存储 缓存 前端开发
伙伴匹配推荐接口的优化策略【优先队列+多线程分批处理,java实现】
伙伴匹配推荐接口的优化策略【优先队列+多线程分批处理,java实现】
123 0
|
人工智能 Java BI
力扣207:课程表(Java拓扑排序:bfs+dfs)
力扣207:课程表(Java拓扑排序:bfs+dfs)
103 0
力扣200:岛屿数量(Java dfs+bfs)
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。