제육's 휘발성 코딩
Published 2021. 10. 23. 17:45
[JAVA] - DFS & BFS (2) 🔷 Java/Basic
반응형

DFS

합이 같은 부분 집합

import java.util.*;

public class Main {
    static int n, total =0;
    static String answer ="NO";
    boolean flag = false;

    public void dfs(int level, int sum, int[] arr) {
        if (flag) return;
        if (sum > total / 2) return;
        if (level == n) {
            if ((total-sum)==sum) {
                answer="YES";
                flag = true;
            }
        }
        else {
            dfs(level+1, sum+arr[level], arr);
            dfs(level+1, sum, arr);
        }
    }

    public static void main(String[] args) {
        Main main = new Main();
        n = 6;
        int[] arr = {1, 3, 5, 6, 7, 10};
        total = Arrays.stream(arr).sum();
        main.dfs(0,0, arr);
        System.out.println(answer);
    }
}

중복 순열

public class Main {
    static int n,m;
    static int[] pm;
    public static void main(String[] args) {
        Main main = new Main();
        Scanner sc = new Scanner(System.in);
        n = 3;
        m = 2;
        pm = new int[m];
        main.dfs(0);
    }

    public void dfs(int level) {
        if(level == m) {
            for (int x : pm) System.out.print(x+ " ");
            System.out.println();
        }
        else {
            for (int i=1; i<=n; i++) {
                pm[level] = i;
                dfs(level+1);
            }
        }
    }
}
[출력]
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3

조합 수 (메모이제이션)

public class Main {
    static int[][] distance;
    static int answer;
    public static void main(String[] args) {
        Main main = new Main();
        Scanner sc = new Scanner(System.in);
        int n = 33;
        int r = 19;
        distance = new int[n+1][r+1];
        System.out.println(main.dfs(n,r));
    }

    public int dfs(int n, int r) {
        if (distance[n][r] != 0) return distance[n][r];
        else if (n == r || r== 0) return 1;
        else {
            return distance[n][r] = dfs(n-1,r-1) + dfs(n-1,r);
        }
    }
}
[입력] 5 3 -> 5C3
[출력] 10
  • nCr = n-1Cr-1 + n-1Cr 을 계산하는 문제
  • distance 배열을 이용해 메모이제이션 적용

수열 추측

import java.util.*;

public class Main {
    static int[] b, p, ch;
    static int n,f;
    boolean flag = false;
    int[][] dy = new int[35][35];

    public int calculate(int n, int r) {
        if (dy[n][r] > 0) return dy[n][r];
        if (n == r || r ==0) return 1;
        else return dy[n][r] = calculate(n-1, r-1) + calculate(n-1, r);
    }

    public static void main(String[] args) {
        Main main = new Main();
        Scanner sc = new Scanner(System.in);
        n = 4;
        f = 16;
        b = new int[n];
        p = new int[n];
        ch = new int[n+1];
        for (int i=0; i<n; i++) {
            b[i] = main.calculate(n-1,i);
        }
        main.dfs(0,0);
    }

    public void dfs(int level, int sum) {
        if (flag) return;
        if (level == n) {
            if (sum == f) {
                for (int index : p) System.out.print(index+" ");
                flag = true;
            }
        }
        else {
            for (int i=1; i<=n; i++) {
                if (ch[i] == 0) {
                    ch[i] = 1;
                    p[level] = i;
                    dfs(level+1, sum+(p[level] * b[level]));
                    ch[i] = 0;
                }
            }
        }
    }
}
  • 파스칼 삼각형 문제

조합

public class Main {
    static int[] combi;
    static int n, m;
    public static void main(String[] args) {
        Main main = new Main();
        Scanner sc = new Scanner(System.in);
        n = 4;
        m = 2;
        combi = new int[m];
        main.dfs(0, 1);
    }

    public void dfs(int level, int start) {
        if (level == m) {
            for (int x : combi) System.out.print(x + " ");
            System.out.println();
        }
        else {
            for (int i=start; i<=n; i++) {
                combi[level] = i;
                dfs(level+1, i+1);
            }
        }
    }
}
[입력] 4 2
[출력]
1 2 
1 3 
1 4 
2 3 
2 4 
3 4 

미로 탐색

public class Main {
    static int[][] board;
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};
    static int answer = 0;
    public static void main(String[] args) {
        Main main = new Main();
        Scanner sc = new Scanner(System.in);
        board = new int[8][8];
        for (int i=1; i<=7; i++) {
            for (int j=1; j<=7; j++) {
                board[i][j] = sc.nextInt();
            }
        }
        board[1][1] = 1;
        main.dfs(1,1);
        System.out.println(answer);
    }

    public void dfs(int x, int y) {
        if (x == 7 && y == 7) {
            answer++;
        }
        else {
            for (int i = 0; i < 4; i++) {
                int nx = x+dx[i];
                int ny = y+dy[i];
                if (nx >= 1  && nx <=7 && ny >=1 && ny <=7 && board[nx][ny] == 0) {
                    board[nx][ny] = 1;
                    dfs(nx,ny);
                    board[nx][ny] = 0;
                }
            }
        }
    }
}
[입력]
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 0 0 1 0 0 0
1 1 0 1 0 1 1
1 1 0 0 0 0 1
1 1 0 1 1 0 0
1 0 0 0 0 0 0
[출력] 8
  • 상하좌우 dx, dy 생성 후 dfs 실행 후 벽을 다시 없애주는게 포인트

섬 구하기

import java.util.*;

class Main {
    static int answer = 0, n;
    static int[] dx = {-1, -1, 0, 1, 1, 1, 0, -1};
    static int[] dy = {0, 1, 1, 1, 0, -1, -1, -1};

    public static void main(String[] args) {
        Main main = new Main();
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        int[][] board = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] = sc.nextInt();
            }
        }
        main.chk(board);
        System.out.println(Arrays.deepToString(board));
        System.out.println(answer);
    }

    public void chk(int[][] board) {
        for (int i=0; i<n; i++) {
            for (int j=0; j<n; j++) {
                if(board[i][j] == 1) {
                    answer++;
                    dfs(board, i,j);
                }
            }
        }
    }

    public void dfs(int[][] board, int x, int y) {
        board[x][y] = 0;
        for (int i=0; i<8; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx>=0 && nx <n && ny >=0 && ny <n && board[nx][ny] == 1) {
                dfs(board, nx,ny);
            }
        }
    }
}
[입력]
7
1 1 0 0 0 1 0
0 1 1 0 1 1 0
0 1 0 0 0 0 0
0 0 0 1 0 1 1
1 1 0 1 1 0 0
1 0 0 0 1 0 0
1 0 1 0 1 0 0
[출력] 5
  • 상하좌우, 대각선 까지 연결된 1의 묶음을 섬으로 보고 섬의 개수 구하는 문제

피자 배달 거리

import java.util.*;

class Point {
    public int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
class Main {
    static int n,m, len, answer =Integer.MAX_VALUE;
    static int[] combi;
    static ArrayList<Point> pz, hs;
    public void dfs(int level, int start){
        if(level == m) {
            int sum = 0;
            for (Point h : hs) {
                int dis = Integer.MAX_VALUE;
                for (int i : combi) {
                    dis = Math.min(dis, Math.abs(h.x - pz.get(i).x) + Math.abs(h.y - pz.get(i).y));
                }
                sum += dis;
            }
            answer = Math.min(answer, sum);
        }
        else {
            for (int i=start; i < len; i++) {
                combi[level] = i;
                dfs(level+1, i+1);
            }
        }
    }


    public static void main(String[] args) {
        Main main = new Main();
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        pz = new ArrayList<>();
        hs = new ArrayList<>();
        for (int i=0; i<n; i++) {
            for (int j=0; j<n; j++) {
                int tmp = sc.nextInt();
                if (tmp == 1) hs.add(new Point(i,j));
                else if (tmp == 2) pz.add(new Point(i,j));
            }
        }
        len = pz.size();
        combi = new int[m];
        main.dfs(0,0);
        System.out.println(answer);
    }

}

BFS

미로 최단 거리

class Point {
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
public class Main {
    static int[][] board, dis;
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};
    public static void main(String[] args) {
        Main main = new Main();
        Scanner sc = new Scanner(System.in);
        board = new int[8][8];
        dis = new int[8][8];
        for (int i=1; i<=7; i++) {
            for (int j=1; j<=7; j++) {
                board[i][j] = sc.nextInt();
            }
        }
        main.bfs(1,1);
        if (dis[7][7] == 0) System.out.println(-1);
        else System.out.println(dis[7][7]);

    }

    public void bfs(int x, int y) {
        Queue<Point> queue = new LinkedList<>();
        queue.offer(new Point(x, y));
        board[x][y] = 1;
        while(!queue.isEmpty()) {
            Point tmp = queue.poll();
            for (int i=0; i<4; i++) {
                int nx = tmp.x + dx[i];
                int ny = tmp.y + dy[i];
                if (nx >=1 && nx <=7 && ny>=1 && ny <= 7 && board[nx][ny] == 0) {
                    board[nx][ny] = 1;
                    queue.offer(new Point(nx, ny));
                    dis[nx][ny] = dis[tmp.x][tmp.y] + 1;
                }
            }
        }
    }
}
[입력]
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 0 0 1 0 0 0
1 1 0 1 0 1 1
1 1 0 1 0 0 0
1 0 0 0 1 0 0
1 0 1 0 0 0 0
[출력] 12
  • n x n 크기의 미로와 동일한 거리 배열 생성 후 제일 먼저 값이 들어간 값이 최단거리로 측정

토마토

import java.util.*;

class Point {
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

public class Main {
    static int[][] board, dis;
    static int n,m;
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 1};
    static Queue<Point> queue = new LinkedList<>();
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Main main = new Main();
        m = sc.nextInt();
        n = sc.nextInt();
        board = new int[n][m];
        dis = new int[n][m];
        for (int i=0; i<n; i++) {
            for (int j=0; j<m; j++) {
                board[i][j] = sc.nextInt();
                if(board[i][j] == 1) queue.offer(new Point(i,j));
            }
        }
        main.bfs();
        boolean flag = true;
        int answer = Integer.MIN_VALUE;
        for (int i=0; i<n; i++) {
            for (int j=0; j<m; j++) {
                if (board[i][j] == 0) flag = false;
            }
        }
        if (flag) {
            for (int i=0; i<n; i++) {
                for (int j=0; j<m; j++) {
                    answer = Math.max(answer, dis[i][j]);
                }
            }
        }
        else answer = -1;
        System.out.println(answer);
    }

    public void bfs() {
        while (!queue.isEmpty()) {
            Point tmp = queue.poll();
            for (int i=0; i<4; i++) {
                int nx = tmp.x + dx[i];
                int ny = tmp.y + dy[i];
                if (nx>=0 && nx <n && ny>=0 && ny <m && board[nx][ny] == 0) {
                    board[nx][ny] = 1;
                    queue.offer(new Point(nx,ny));
                    dis[nx][ny] = dis[tmp.x][tmp.y]+1;
                }
            }
        }
    }
}
[입력]
6 4
0 0 -1 0 0 0
0 0 1 0 -1 0
0 0 -1 0 0 0
0 0 0 0 -1 1
[출력] 4
  • 익은 토마토 1, 안익은 토마토 0, 없는 자리 -1 이며, 익은 토마토 주변 상하좌우가 하루에 1개씩 익는 최단 거리 문제

섬 구하기

import java.util.*;

class Point {
    public int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
class Main {
    static int answer = 0, n;
    static int[] dx = {-1, -1, 0, 1, 1, 1, 0, -1};
    static int[] dy = {0, 1, 1, 1, 0, -1, -1, -1};
    static Queue<Point> queue = new LinkedList<>();

    public static void main(String[] args) {
        Main main = new Main();
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        int[][] board = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] = sc.nextInt();
            }
        }
        main.chk(board);
        System.out.println(Arrays.deepToString(board));
        System.out.println(answer);
    }

    public void chk(int[][] board) {
        for (int i=0; i<n; i++) {
            for (int j=0; j<n; j++) {
                if(board[i][j] == 1) {
                    answer++;
                    queue.offer(new Point(i,j));
                    bfs(board);
                }
            }
        }
    }

    public void bfs(int[][] board) {
        while (!queue.isEmpty()) {
            Point tmp = queue.poll();
            for (int i=0; i<8; i++) {
                int nx = tmp.x + dx[i];
                int ny = tmp.y + dy[i];
                if (nx >=0 && nx <n && ny>=0 && ny <n && board[nx][ny] == 1) {
                    board[nx][ny] = 0;
                    queue.offer(new Point(nx,ny));
                }
            }
        }
    }
}
  • DFS 에 있는 섬 구하기와 동일한 문제 BFS 버전
반응형
profile

제육's 휘발성 코딩

@sasca37

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요! 맞구독은 언제나 환영입니다^^