[백준 15684] 사다리 조작

최민길(Gale)·2023년 7월 1일
1

알고리즘

목록 보기
80/172

문제 링크 : https://www.acmicpc.net/problem/15684

이 문제는 백트래킹을 이용하여 풀 수 있습니다. 이 문제는 문제 특성상 일반 백트래킹과 살짝 다른 방식으로 접근합니다. 주어진 문제에서 가로선의 개수가 모든 가로선의 개수가 아니라 a번과 a+1번을 연결하는 가로선의 개수만 보여주고 대신 세로선마다 가로선을 놓을 수 있는 개수가 주어지기 때문에 한 세로선을 기준으로 놓을 수 있는 위치에 모두 사다리를 놓아보고 해제하는 방식으로 백트래킹을 진행합니다. 이후 정답이 3보다 작거나 같으므로 0부터 3까지 가능한 정답을 반복문을 돌려 해당 수만큼 사다리를 추가했다면 모든 세로선이 자기 자신으로 도착하는지를 체크합니다. 이 때 체크 방식은 각 세로선 별로 가능한 모든 사다리를 탐색하면서 사다리가 왼쪽에 있다면 세로선을 -1만큼 이동하고 사다리가 오른쪽에 있다면 세로선을 1만큼 이동시켜 모든 사다리를 탐색 완료했을 때 현재 세로선이 초기의 i값과 같다면 통과하는 방식으로 체크합니다.

다음은 코드입니다.

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

class Main{
    static int N,M,H;
    static boolean[][] ladder;
    static boolean canMake = false;

    public static void main(String[] args) throws Exception{
        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());
        ladder = new boolean[N+2][H+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());
            ladder[b][a] = true;
        }

        for(int i=0;i<=3;i++){
            backtracking(i,0,1);
            if(canMake){
                System.out.println(i);
                return;
            }
        }
        System.out.println(-1);
    }

    static void backtracking(int targetLadderNum, int currLadderNum, int idx){
        if(currLadderNum > targetLadderNum) return;
        if(currLadderNum == targetLadderNum){
            for(int i=1;i<=N;i++){
                int row = i;
                for(int j=1;j<=H;j++){
                    if(ladder[row][j]) row++;
                    else if(ladder[row-1][j]) row--;
                    if(j==H && row!=i) return;
                }
            }
            canMake = true;
            return;
        }

        // 1부터 N까지의 세로줄에 사다리를 현재 놓을 수 있는 개수민큼 놓기
        for(int i=1;i<=N;i++){
            for(int j=idx;j<=H;j++){
                if(ladder[i][j] || ladder[i+1][j] || ladder[i-1][j]) continue;

                ladder[i][j] = true;
                backtracking(targetLadderNum,currLadderNum+1,j);
                ladder[i][j] = false;
            }
        }
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글

관련 채용 정보