Java算法模板

该篇文章主要讨论了使用BFS算法解决迷宫中从左上角到右下角的最短路径问题,并利用并查集处理合根植物的数量计算
摘要由CSDN通过智能技术生成

BFS

走迷宫

给定一个 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.io.*;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {
static Scanner sc = new Scanner(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st = new StreamTokenizer(br);
static PrintWriter pw=new PrintWriter(new OutputStreamWriter(System.out));
public static int nextInt()throws Exception{
    st.nextToken();
    return (int)st.nval;
}
public static long nextLong()throws Exception {
st.nextToken();
return (long)st.nval;
}
    public static String next()throws Exception{
        st.nextToken();
        return st.sval;
    }
    public static double nextDouble()throws Exception{
        st.nextToken();
        return (double) st.nval;
    }
public static String nextLine()throws Exception {
    return br.readLine();
}
static int m;
static int n;
static Queue<pair>q=new LinkedList<>();
static int[][]dir={{1,0},{-1,0},{0,1},{0,-1}};
static int[][]a=new int[101][101];
static int[][]b=new int[101][101];


   public static class pair{
        int x;
        int y;
        int step=0;

       public pair(int x, int y, int step) {
           this.x = x;
           this.y = y;
           this.step = step;
       }
   }
static int bfs(){
      int x,y;
       q.add(new pair(0,0,0));
       while(!q.isEmpty()){
           pair p=q.poll();
           if(p.x==m-1&&p.y==n-1){
               return p.step;
           }
          for(int i=0;i<4;i++){
              x=p.x+dir[i][0];
              y=p.y+dir[i][1];
              if(x>=0&&x<m&&y>=0&&y<n&&a[x][y]==0&&b[x][y]==0){
                  b[x][y]=1;
                  q.add(new pair(x,y,p.step+1));
              }
          }


       }

     return  0;
}




    public static void main(String[] args)throws Exception {

m=nextInt();
n=nextInt();
for(int i=0;i<m;i++){
    for(int j=0;j<n;j++){
        a[i][j]=nextInt();
    }
}
        System.out.println(bfs());










    }

}

DFS

迷宫

一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由 n∗n 的格点组成,每个格点只有2种状态,.#,前者表示可以通行后者表示不能通行。

同时当Extense处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,Extense想要从点A走到点B,问在不走出迷宫的情况下能不能办到。

如果起点或者终点有一个不能通行(为#),则看成无法办到。

注意:A、B不一定是两个不同的点。

输入格式

第1行是测试数据的组数 k,后面跟着 k 组输入。

每组测试数据的第1行是一个正整数 n,表示迷宫的规模是 n∗n 的。

接下来是一个 n∗n 的矩阵,矩阵中的元素为.或者#

再接下来一行是 4 个整数 ha,la,hb,lb描述 AA 处在第 haha 行, 第 la 列,B 处在第 hb 行, 第 lb 列。

注意到 ha,la,hb,lb 全部是从 0 开始计数的。

输出格式

k行,每行输出对应一个输入。

能办到则输出“YES”,否则输出“NO”。

数据范围

1≤n≤100

输入样例:
2
3
.##
..#
#..
0 0 2 2
5
.....
###.#
..#..
###..
...#.
0 0 4 0
输出样例:
YES
NO
import java.io.*;
import java.util.*;


public class Main{
static Scanner sc = new Scanner(System.in);
static BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st=new StreamTokenizer(br);
static int nextInt() throws Exception{
    st.nextToken();
    return (int)st.nval;
}
    static double nextDouble() throws Exception{
        st.nextToken();
        return (double)st.nval;
    }
    static long nextLong() throws Exception{
        st.nextToken();
        return (long)st.nval;
    }

    static String next() throws Exception{
        st.nextToken();
        return st.sval;
    }
    static String nextLine() throws Exception{
       return br.readLine();
    }
    static int N=110,row,col;
static char[][] a=new char[N][N];
static int[][] dir=new int[][]{{0,1},{0,-1},{1,0},{-1,0}};




    public static void main(String[] args) throws Exception{
int m=Integer.valueOf(nextLine());
while(m-->0){
    int n=Integer.valueOf(nextLine());
    row=col=n;
    for(int i=0;i<n;i++){
     String s=nextLine();
        for(int j=0;j<n;j++){
            a[i][j]=s.charAt(j);
        }
    }
String[] ss=nextLine().split(" ");
    int x1=Integer.parseInt(ss[0]);
    int y1=Integer.parseInt(ss[1]);
    int x2=Integer.parseInt(ss[2]);
    int y2=Integer.parseInt(ss[3]);
    boolean[][] vis=new boolean[n][n];
    if(a[x1][y1]=='#'||a[x2][y2]=='#'){
        System.out.println("NO");
    } else if (x1==x2&&y1==y2){
        System.out.println("YES");

    } else if(dfs(x1,y1,x2,y2,vis)){
        System.out.println("YES");
    }else{
        System.out.println("NO");
    }




}



    }
public static boolean dfs(int x1,int y1,int x2,int y2,boolean[][] vis) {
    for (int i = 0; i < 4; i++) {
        int nx = x1 + dir[i][0];
        int ny = y1 + dir[i][1];
if(nx<0||nx>=row||ny<0||ny>=col||a[nx][ny]=='#'||vis[nx][ny])continue;
vis[nx][ny]=true;
if(nx==x2&&ny==y2)return true;
if(dfs(nx,ny,x2,y2,vis))return true;


    }
    return false;
}






}

并查集

合根植物

题目描述

w星球的一个种植园,被分成 m * n 个小格子(东西方向m行,南北方向n列)。每个格子里种了一株合根植物。
这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。

 

如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?

输入格式

第一行,两个整数m,n,用空格分开,表示格子的行数、列数(1<m,n<1000)。
接下来一行,一个整数k,表示下面还有k行数据(0<k<100000)
接下来k行,第行两个整数a,b,表示编号为a的小格子和编号为b的小格子合根了。


格子的编号一行一行,从上到下,从左到右编号。
比如:5 * 4 的小格子,编号:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20

输出格式

多少株

样例输入

复制

5 4
16
2 3
1 5
5 9
4 8
7 8
9 10
10 11
11 12
10 14
12 16
14 18
17 18
15 19
19 20
9 13
13 17

样例输出

复制

5
import java.util.Arrays;
import java.util.Scanner;
public class Main{
    static int inf=0x3f3f3f3f;
    static int maxn=10051005;
    static int m,n,k,ans;
    static int[] p=new int[maxn];
    static Scanner sc=new Scanner(System.in);
static boolean[] vis=new boolean[maxn];
    public static void init(){
        Arrays.fill(vis,false);
        for (int i = 1; i <= n * m; i++) {
            p[i]=i;
        }
    }
  public static int find(int x){
        if(x!=p[x]){
            return p[x]=find(p[x]);
        }return x;
    }
    public static void join(int x, int y){
        int xx=find(x);
        int yy=find(y);
        if(xx!=yy)p[yy]=xx;
    }
 
 
 
    public static void main(String[] args) {
 
m= sc.nextInt();
n= sc.nextInt();
k= sc.nextInt();
init();
 
while (k-->0){
    int x,y;
    x= sc.nextInt();
    y= sc.nextInt();
    join(x,y);
}
for(int i=1;i<=m*n;i++){
    vis[find(i)]=true;
 
}
        for (int i = 1; i <= n * m; i++) {
            if(vis[i])ans++;
        }
 
        System.out.println(ans);
 
 
    }
 
 
 
}

  • 14
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值