본문 바로가기
알고리즘/백준

[Java] BOJ 15684번 사다리 조작

by 컴공맨 2021. 8. 18.
 

15684번: 사다리 조작

사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선

www.acmicpc.net


풀이

순열을 사용하여 해결했습니다.

자세한 내용은 코드의 주석을 참고해주세요.


코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	public static int N, M, H;
	public static boolean[][] ladder;
	public static void main(String[] args) 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());
		
		ladder = new boolean[H][N];
		
		for (int i = 0; i < M; ++i) {
			st = new StringTokenizer(br.readLine(), " ");
			
			// 문제에서는 인덱스가 1부터 시작함을 주의
			int a = Integer.parseInt(st.nextToken()) - 1;
			int b = Integer.parseInt(st.nextToken()) - 1;
			
			// 왼쪽이 true면 오른쪽과 연결되있음을 알려준다.
			ladder[a][b] = true;
		}
		
		// 최대 3개까지의 가로선을 추가할 수 있으므로
		// 아예 설치를 하지않는 0부터 3까지 가로선을 
		// 순열을 통해 추가하도록 한다.
		for (int i = 0; i < 4; ++i) {
			permutation(0, i);
		}
		
		System.out.println(-1);
	}
	
	// i번에서 시작하는 세로선이 i번에 도착하는지 검사
	public static boolean check() {
		for (int j = 0; j < N; ++j) {
			// 현재 세로선의 번호를 기록
			int cur = j;
			
			for (int i = 0; i < H; ++i) {
				if (cur - 1 >= 0 && ladder[i][cur - 1]) {
					// 만약 왼쪽이 true라면 왼쪽과 연결
					cur -= 1;
				}
				else if (cur + 1 < N && ladder[i][cur]) {
					// 만역 오른쪽이 true라면 오른쪽과 연결
					cur += 1;
				}
			}
			
			// 출발한 번호와 도착 번호가 다르다면 false
			if (cur != j) {
				return false;
			}
		}
		
		// 모든 조건을 봐서 정상적이면 true
		return true;
	}
	
	public static void permutation(int cnt, int maxCnt) {
		// 최대로 추가할 수 있는 가로선 개수만큼 추가했다면
		if (cnt == maxCnt) {
			// 문제에서 요구한 조건을 충족하는지 검사
			if (check()) {
				// main문에서 추가할 수 있는 가로선 개수가 작은 수부터 조사하므로
				// 먼저 조건에 충족한다면 더이상 검사할 필요가 없다.
				System.out.println(cnt);
				System.exit(0);
			}
			
			// 만약 요구한 조건을 충족하지 못했다면 다른 조건을 볼 수 있도록
			// 반환
			return;
		}
		
		for (int i = 0; i < H; ++i) {
			// 왼쪽이 true라면 오른쪽과 연결되 있으므로 N-1까지만 반복
			for (int j = 0; j < N - 1; ++j) {
				// 만약 이미 오른쪽과 연결되 있을 경우 가로선 추가 X
				if (ladder[i][j]) {
					continue;
				}
				
				// 이미 왼쪽 점과 연결되 있을 경우 가로선 추가 X
				if (j - 1 >= 0 && ladder[i][j - 1]) {
					continue;
				}
				
				// 이미 오른쪽의 점이 그 오른쪽의 점과 연결되 있을 경우 가로선 추가 X
				if (j + 1 < N && ladder[i][j + 1]) {
					continue;
				}
				
				// 가로선을 추가할 수 있으므로 오른쪽 점과 연결
				ladder[i][j] = true;
				// 모든 경우를 조사
				permutation(cnt + 1, maxCnt);
				// 다른 경우를 조사하기 위해 다시 초기화
				ladder[i][j] = false;
			}
		}
	}
}

 

GitHub - pyo7410/Algorithm: 1일 1커밋을 목표로!

1일 1커밋을 목표로! Contribute to pyo7410/Algorithm development by creating an account on GitHub.

github.com

 

'알고리즘 > 백준' 카테고리의 다른 글

[Java] BOJ 9935번 문자열 폭발  (0) 2021.08.22
[Java] BOJ 1976번 여행 가자  (0) 2021.08.20
[Java] BOJ 17298번 오큰수  (0) 2021.08.12
[Java] BOJ 1339번 단어 수학  (0) 2021.08.11
[Java] BOJ 1967번 트리의 지름  (0) 2021.08.09