본문 바로가기

알고리즘/BFS, DFS

[자바] 백준 16173번 점프왕 쩰리(Small)[탐색][엄탱]

728x90

문제

‘쩰리’는 점프하는 것을 좋아하는 젤리다. 단순히 점프하는 것에 지루함을 느낀 ‘쩰리’는 새로운 점프 게임을 해보고 싶어 한다. 새로운 점프 게임의 조건은 다음과 같다.

  1. ‘쩰리’는 가로와 세로의 칸 수가 같은 정사각형의 구역 내부에서만 움직일 수 있다. ‘쩰리’가 정사각형 구역의 외부로 나가는 경우엔 바닥으로 떨어져 즉시 게임에서 패배하게 된다.
  2. ‘쩰리’의 출발점은 항상 정사각형의 가장 왼쪽, 가장 위의 칸이다. 다른 출발점에서는 출발하지 않는다.
  3. ‘쩰리’가 이동 가능한 방향은 오른쪽과 아래뿐이다. 위쪽과 왼쪽으로는 이동할 수 없다.
  4. ‘쩰리’가 가장 오른쪽, 가장 아래 칸에 도달하는 순간, 그 즉시 ‘쩰리’의 승리로 게임은 종료된다.
  5. ‘쩰리’가 한 번에 이동할 수 있는 칸의 수는, 현재 밟고 있는 칸에 쓰여 있는 수만큼이다. 칸에 쓰여 있는 수 초과나 그 미만으로 이동할 수 없다.

새로운 게임이 맘에 든 ‘쩰리’는, 계속 게임을 진행해 마침내 최종 단계에 도달했다. 하지만, 게임을 진행하는 구역이 너무 넓어져버린 나머지, 이 게임에서 이길 수 있는지 없는지 가늠할 수 없어졌다. ‘쩰리’는 유능한 프로그래머인 당신에게 주어진 구역에서 승리할 수 있는지 알아봐 달라고 부탁했다. ‘쩰리’를 도와 주어진 게임 구역에서 끝 점(오른쪽 맨 아래 칸)까지 도달할 수 있는지를 알아보자!

입력

입력의 첫 번째 줄에는 게임 구역의 크기 N (2 ≤ N ≤ 3)이 주어진다.

입력의 두 번째 줄부터 마지막 줄까지 게임판의 구역(맵)이 주어진다.

게임판의 승리 지점(오른쪽 맨 아래 칸)에는 -1이 쓰여있고, 나머지 칸에는 0 이상 100 이하의 정수가 쓰여있다.

출력

‘쩰리’가 끝 점에 도달할 수 있으면 “HaruHaru”(인용부호 없이), 도달할 수 없으면 “Hing” (인용부호 없이)을 한 줄에 출력합니다.

예제

문제 설명

점프왕 쩰리 문제는 정사각형 보드판 위에 쩰리가 첫 위치 (0,0)에서 끝 위치(N - 1, N -1)로 이동 가능하는지 판단 하는 문제이다.

이동할 수 있는 칸은 쩰리가 밟고 있는 칸에 쓰여있고, 이동 가능한 방향은 오른쪽과 아래만 가능하다.

중요한건 이동할 수 있는 칸이 3이라면 3칸을 이동해야 한다. 1칸 2칸은 이동하면 안 된다.

해설

점프왕 쩰리 문제는 이동 가능한 구역을 오른쪽 아래 하나하나 탐색하면서 끝 위치에 도달할 수 있는지 파악하면 된다.

  • 완전 탐색으로 하면 안 된다.
  • 현재 밟고 있는 칸에 적혀있는 이동 가능 칸을 이용하여 BFS 혹은 DFS 탐색을 사용
  • 끝 위치에 도달하면  "HaruHaru"를 도달할 수 없으면 "Hing"을 출력하자

나는 DFS를 사용하여 풀었지만 BFS 탐색을 해도 상관없다.

DFS 탐색을 Stack, 재귀를 이용해 두 가지 방식으로 풀었다.

1. Stack을 이용한 DFS 코드

import java.io.*;
import java.util.*;

public class Main {
    static int N;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        N = Integer.parseInt(br.readLine());

        int[][] board = new int[N][N];
        for (int i = 0; i < N; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine(), " ");

            for (int j = 0; j < N; j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        System.out.println(dfs(board));

        br.close();
    }

    static public String dfs(int[][] board) {
        Stack<Node> stack = new Stack<>();
        boolean[][] visited = new boolean[N][N];
        stack.add(new Node(0, 0, board[0][0]));

        while(!stack.isEmpty()) {
            Node cur = stack.pop();

            int x = cur.x;
            int y = cur.y;
            int count = cur.count;

            if (board[x][y] == -1) {
                return "HaruHaru";
            }

            if (visited[x][y]) {
                continue;
            }

            visited[x][y] = true;

            if (x + count < N && !visited[x + count][y]) {
                stack.add(new Node(x + count, y, board[x + count][y]));
            }

            if (y + count < N && !visited[x][y + count]) {
                stack.add(new Node(x, y + count, board[x][y + count]));
            }
        }

        return "Hing";
    }
}

class Node {
    int x;
    int y;
    int count;

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

2. 재귀함수를 이용한 코드

import java.io.*;
import java.util.*;

public class Main {
    static int N;
    static int[][] board;
    static boolean[][] visited;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        N = Integer.parseInt(br.readLine());

        board = new int[N][N];
        visited = new boolean[N][N];
        for (int i = 0; i < N; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine(), " ");

            for (int j = 0; j < N; j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        System.out.println(dfs(0, 0));

        br.close();
    }

    static public String dfs(int x, int y) {
        int count = board[x][y];

        visited[x][y] = true;

        if (count == -1) {
            return "HaruHaru";
        }

        if (x + count < N && !visited[x + count][y] && !dfs(x + count, y).equals("Hing")) {
            return "HaruHaru";
        }

        if (y + count < N && !visited[x][y + count] && !dfs(x, y + count).equals("Hing")) {
            return "HaruHaru";
        }
        
        return "Hing";
    }
}

 

728x90