본문 바로가기
문제풀이/백준

[JAVA] BOJ 백준 15684번 - 사다리 조작

by 그적 2023. 9. 27.

목차

  • 문제
  • 내가 푼 방법
  • 자바 코드
  • 결과 및 회고

1. 문제

https://www.acmicpc.net/problem/15684

 


2. 내가 푼 방법

완전 탐색이 필요한 문제이다. 이 문제를 풀 때는 가로, 세로 길이를 주의해야 한다고 생각한다.

 

가로 길이 N과 세로 길이 H를 입력받고, boolean 자료형을 가진 사다리 배열을 선언해준다.

사다리 배열 범위를 N+1, H+1로 지정해 줬는데, arr[i][j] = true라면 세로줄 i와 i+1을 잇는 j번째 가로줄로 설정해두었다.

StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
H = Integer.parseInt(st.nextToken());

arr = new boolean[H+1][N+1];

for (int i = 0; i < M; i++) {
    st = new StringTokenizer(br.readLine());
    int a = Integer.parseInt(st.nextToken());
    int b = Integer.parseInt(st.nextToken());

    arr[a][b] = true;
}

 

사다리를 조작하기 전, result를 Integer.MAX_VALUE로 설정해두었다.

 

사다리를 조작할 수 있는 완전탐색 부분은 controlLadder에 있는 이중 for문 부분이며, 시간 초과를 해결하기 위해 x와 y 이후에 있는 사다리 값을 판단한다.

가로선이 연속하면 안 되므로 arr[i][j], arr[i][j-1], arr[i][j+1]을 확인해주어 가로선을 만들 수 있는지를 확인한다.

(※ 만들 수 있는 가로선을 확인할 때(controlLadder)와 i번째 사다리가 i번째 결과를 가지는지 확인할 때(checkLadder) i, j 범위가 다르다)

public static void solution() {
    result = Integer.MAX_VALUE;

    controlLadder(1, 1, 0);
}

public static void controlLadder(int x, int y, int cnt) {
    if (checkLadder()) {
        result = Math.min(result, cnt);
        return;
    }
    if (cnt == 3) return;

    for (int i = x; i <= H; i++) {
        for (int j = 1; j < N; j++) {
            if (i == x && j < y) continue;

            if (j-1 > 0 && arr[i][j-1]) continue;
            if (arr[i][j]) continue;
            if (j+1 < N && arr[i][j+1]) continue;

            arr[i][j] = true;
            controlLadder(i, j, cnt+1);
            arr[i][j] = false;
        }
    }
}

public static boolean checkLadder() {
    for (int j = 1; j <= N; j++) {
        int line = j;

        for (int i = 1; i <= H; i++) {
            if (arr[i][line-1]) line -= 1;
            else if (arr[i][line]) line += 1;
        }

        if (line != j) return false;
    }
    return true;
}

 


3. 자바 코드

깃허브 풀이 주소

https://github.com/geujeog/BOJ/blob/main/B15684.java

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

class Main {
    static int N;
    static int H;
    static int M;
    static boolean[][] arr;
    static int result;

    public static void main (String[] args) throws IOException {
        init();
        solution();
        print();
    }

    public static void solution() {
        result = Integer.MAX_VALUE;

        controlLadder(1, 1, 0);
    }

    public static void controlLadder(int x, int y, int cnt) {
        if (checkLadder()) {
            result = Math.min(result, cnt);
            return;
        }
        if (cnt == 3) return;

        for (int i = x; i <= H; i++) {
            for (int j = 1; j < N; j++) {
                if (i == x && j < y) continue;

                if (j-1 > 0 && arr[i][j-1]) continue;
                if (arr[i][j]) continue;
                if (j+1 < N && arr[i][j+1]) continue;

                arr[i][j] = true;
                controlLadder(i, j, cnt+1);
                arr[i][j] = false;
            }
        }
    }

    public static boolean checkLadder() {
        for (int j = 1; j <= N; j++) {
            int line = j;

            for (int i = 1; i <= H; i++) {
                if (arr[i][line-1]) line -= 1;
                else if (arr[i][line]) line += 1;
            }

            if (line != j) return false;
        }
        return true;
    }

    public static void print() throws IOException {
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        if (result == Integer.MAX_VALUE) bw.write(-1+"");
        else bw.write(result+"");

        bw.flush();
        bw.close();
    }

    public static void init() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        H = Integer.parseInt(st.nextToken());

        arr = new boolean[H+1][N+1];

        for (int i = 0; i < M; i++) {
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());

            arr[a][b] = true;
        }

        br.close();
    }
}

4. 결과 및 회고

사다리 가로선을 이을 수 있는 범위를 설정하는 것이 관건인 것 같다. 분명 arr[i][j] = true면 세로줄 i와 i+1을 잇는 j번째 가로선이었는데 헷갈려서 삽질을 했던 부분도 있었다. 다른 분들은 그러지 마시길! ㅎㅎ

 

댓글