Java刷算法之基于模拟队列的BFS

板子

首先将BFS板子拿出来,通过数组构造模拟队列,实现宽度优先搜索(BFS)。宽度优先搜索适用范围:问题要求最短路径。例如:求从左上角走到右下角最少需要走多少步。常见BFS题型:迷宫问题。

public static int BFS(){
        int hh=0,tt=0;
        q[0]=new Pair(0, 0);//将初始点加入队列
        for(int[] item:d)Arrays.fill(item,-1);//将距离数组初始化
        d[0][0]=0;//将距离矩阵开头初始化为0
        int []dx={-1,0,1,0},dy={0,1,0,-1};//方向数组
        //当模拟队列不为空
        while(hh<=tt){
            Pair head=q[hh++];//取出队头
            for(int i=0;i<4;i++){
                int x=head.x+dx[i],y=head.y+dy[i];
                if(x>=0&&x<n&&y>=0&&y<m&&a[x][y]==0&&d[x][y]==-1){
                    d[x][y]=d[head.x][head.y]+1;
                    q[++tt]=new Pair(x, y);//添加入队列
                    
                }
            }
        }
        return d[n-1][m-1];
    }

题目1----走迷宫

给定一个 n×m 的二维整数数组,用来表示一个迷宫,数组中只包含 0 或 1,其中 0 表示可以走的路,1 表示不可通过的墙壁。最初,有一个人位于左上角 (1,1) 处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。请问,该人从左上角移动至右下角 (n,m) 处,至少需要移动多少次。数据保证 (1,1) 处和 (n,m) 处的数字为 0,且一定至少存在一条通路。
输入格式
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含 m 个整数(0 或 1),表示完整的二维数组迷宫。
输出格式
输出一个整数,表示从左上角移动至右下角的最少移动次数。
数据范围
1≤n,m≤100

样例

输入样例:
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出样例:
8

完整代码

import java.util.*;
public class 走迷宫 {
    static int maxn=1010,m,n;
    static int [][]a=new int[maxn][maxn];
    static int [][]d=new int[maxn][maxn];//距离
    static Pair[]q=new Pair[maxn*maxn];//模拟队列
    public static void main(String []args){
        Scanner input=new Scanner(System.in);
        n=input.nextInt();
        m=input.nextInt();
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                a[i][j]=input.nextInt();
            }
        }
        System.out.println(BFS());
        input.close();
    }
    public static int BFS(){
        int hh=0,tt=0;
        q[0]=new Pair(0, 0);//将初始点加入队列
        for(int[] item:d)Arrays.fill(item,-1);//将距离数组初始化
        d[0][0]=0;//将距离矩阵开头初始化为0
        int []dx={-1,0,1,0},dy={0,1,0,-1};//方向数组
        //当模拟队列不为空
        while(hh<=tt){
            Pair head=q[hh++];//取出队头
            for(int i=0;i<4;i++){
                int x=head.x+dx[i],y=head.y+dy[i];
                if(x>=0&&x<n&&y>=0&&y<m&&a[x][y]==0&&d[x][y]==-1){
                    d[x][y]=d[head.x][head.y]+1;
                    q[++tt]=new Pair(x, y);
                    
                }
            }
        }
        return d[n-1][m-1];
    }
}
class Pair{//构造坐标类
    int x;
    int y;
    public Pair(int x,int y){
        this.x=x;
        this.y=y;
    }
}

题目2----机器人的运动范围

地上有一个 m 行和 n 列的方格,横纵坐标范围分别是 0∼m−1 和 0∼n−1。一个机器人从坐标 (0,0) 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格。但是不能进入行坐标和列坐标的数位之和大于 k 的格子。请问该机器人能够达到多少个格子?

样例

输入:k=7, m=4, n=5

输出:20

完整代码

import java.util.Arrays;
import java.util.Scanner;
public class 机器人的运动范围 {
    static boolean check(int x,int y,int k){//数位和检查函数
        int sum=0;
        while(x!=0){
            sum+=x%10;
            x/=10;
        }
        while(y!=0){
            sum+=y%10;
            y/=10;
        }
        return sum>k?false:true;
    }
    public static void main(String []args){
        Scanner input=new Scanner(System.in);
        int k=input.nextInt();
        int m=input.nextInt();
        int n=input.nextInt();
        System.out.println(bfs(m,n,k));
        input.close();
    }
    public static int bfs(int m,int n,int k){
        int[][]d=new int[m+1][n+1];
        Pair[]q=new Pair[m*n+1];
        if(m==0||n==0)return 0;
        if(k==0)return 1;
        int tt=0,hh=0;
        q[0]=new Pair(0, 0);
        for(int[]item:d)Arrays.fill(item, 0);
        int res=0;
        int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
        while(hh<=tt){
            Pair head=q[hh++];
            for(int i=0;i<4;i++){
                int x=head.x+dx[i],y=head.y+dy[i];
                if(x>=0&&x<m&y>=0&&y<n&&d[x][y]==0&&check(x, y,k)){
                    res++;
                    d[x][y]=1;
                    q[++tt]=new Pair(x, y);
                }
            }
        }
        return res;
    }
}
class Pair{//坐标类
    int x;
    int y;
    public Pair(int x,int y){
        this.x=x;
        this.y=y;
    }
}

题目3----海上救援任务

广阔的大海地图可以由矩形阵列表示。
矩阵的元素由数字0和1组成。0表示海水。数字1代表军舰。
同一舰队的定义为沿军舰数字上下左右还是军舰数字1则为同一舰队。
求给定矩形阵列的舰队个数。如:矩阵
0111100011
1011110100
1011100111
0000000011
有4个舰队。
其中有艘军舰发生故障,负责救援的人员从固定的救援军舰赶往故障处。处于安全考虑,救援人员只能通过舰队内部到达故障点。

【输入格式】
第一行两个整数n,m (1 < = n,m< = 100)
下来是n×m矩阵
下来一行K(1 < = K < =2000) ,代表下来K行有K个询问。每行为X1,Y1,X2,Y2代表两艘军舰的海上坐标。

【输出格式】
如果两艘军舰属于同一舰队那么输出它们之间最短的内部距离,若两艘军舰不属于同一舰队,那么请输出"Impossible".
注意: 舰队由军舰构成。

样例

【样例输入】
4 10
0 1 1 1 1 0 0 0 1 1
1 0 1 1 1 1 0 1 0 0
1 0 1 1 1 0 0 1 1 1
0 0 0 0 0 0 0 0 1 1
2
1 3 2 6
1 3 4 10
【样例输出】
4
Impossible

完整代码

import java.util.*;
public class 海上救援任务 {
    static int maxn=2010,m,n;
    static int [][]a=new int[maxn][maxn];
    static Pair[]q=new Pair[maxn*maxn];
    static int [][]d=new int[maxn][maxn];
    public static void main(String[]args){
        Scanner input=new Scanner(System.in);
        n=input.nextInt();
        m=input.nextInt();
        //输入阵列
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                a[i][j]=input.nextInt();
            }
        }
        int k=input.nextInt();
        for(int i=0;i<k;i++){
            int x1=input.nextInt();
            int y1=input.nextInt();
            int x2=input.nextInt();
            int y2=input.nextInt();
            BFS(x1,y1,x2,y2);
        }
        input.close();
    }
    public static void BFS(int x1,int y1,int x2,int y2){
        int hh=0,tt=0;
        q[0]=new Pair(x1,y1);
        boolean flag=false;
        for(int[] item:d)Arrays.fill(item,-1);//初始化距离矩阵
        d[x1][y1]=0;
        int []dx={-1,0,1,0};
        int []dy={0,1,0,-1};
        while(hh<=tt){//队列不为空
            Pair head=q[hh++];//取出队头
            for(int i=0;i<4;i++){
                int xt=head.x+dx[i],yt=head.y+dy[i];
                if(xt>=1&&xt<=n&&yt>=1&&yt<=m&&d[xt][yt]==-1&&a[xt][yt]==1){
                    d[xt][yt]=d[head.x][head.y]+1;
                    q[++tt]=new Pair(xt, yt);
                    if(xt==x2&&yt==y2){
                        flag=true;
                        System.out.println(d[xt][yt]);
                        break;
                    }
            }
                }
        }
        if(!flag){System.out.println("Impossible");}
    }
}
class Pair{
     int x;
     int y;
     public Pair(int x,int y){
         this.x=x;
         this.y=y;
     }
 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿宇阿星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值