문제
https://www.acmicpc.net/problem/15684
15684번: 사다리 조작
사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선
www.acmicpc.net
문제 요약
N개의 세로선과 M개의 가로선으로 이루어져 있는 사다리 게임이 있다.
가로선을 놓을 수 있는 점선의 개수는 H이다.
가로선을 추가해서 i번 세로선의 결과가 i번이 나오도록 하기 위해 필요한 가로선 개수의 최소값을 출력한다.
가장 위에 있는 점선의 번호와 가장 왼쪽에 있는 세로선의 번호는 1번이다.
+ 가로선은 두 개이상 연속할 수 없다.
코드
import sys
input = __import__('sys').stdin.readline
def check():
# i번 세로선이 i번으로 도착하는지 확인
for start in range(N):
# 1번 부터 N번 세로선까지 검사
# start는 출발 좌표이자 도착해야하는 좌표
j = start
# j는 현재 몇번째 열(세로선)에 있는지 표시하는 좌표
for i in range(H):
# 가로선(행) 이동
if board[i][j]:
# 현재 열에 가로선의 좌표가 표시되어 있다면,
j += 1
# 오른쪽 열로 이동
elif j > 0 and board[i][j - 1]:
# 현재 열 바로 왼쪽 열에 가로선 좌표가 표시되어 있다면,
j -= 1
# 왼쪽 열로 이동
if j != start:
# 가장 하단 까지 왔는데 시작했던 열 좌표가 아니라면,
return False
# 원하는 결과가 아니므로 False 반환
return True
def dfs(cnt, x, y):
# cnt는 추가한 가로선의 개수, x와 y는 현재 검사하는 좌표
global ans
if check():
# 현재 상태에서 각 출발점의 열 좌표와 도착점의 열 좌표가 같다면
ans = min(ans, cnt)
# 저장되어 있던 ans값과 비교하여 재설정
return
elif cnt == 3 or ans <= cnt:
# 추가한 가로선의 개수가 3개인데 위 조건문에서 조건에 부합하지 않았을 경우 그다음 호출에서 4개가 됨으로 조건 위반
# 추가한 가로선의 개수가 이전에 저장했던 ans값보다 클 경우 더이상 볼 필요 X
return
for i in range(x, H):
# i는 현재 가로선을 추가할 행, x는 현재 검사하는 행
if i == x:
# 같은 행에서 계속해서 가로선을 추가하려는 상황
k = y
# y열부터 계속해서 검사
else:
# 새로운 행에서 계속해서 가로선을 추가하려는 상황
k = 0
# 0열부터 다시 검사
for j in range(k, N - 1):
if not board[i][j - 1] and not board[i][j] and not board[i][j + 1]:
# 가로선을 추가하려는 인덱스와 그 왼쪽, 오른쪽 인덱스에 아직 가로선이 없다면
board[i][j] = 1 # 가로선 놓기
dfs(cnt + 1, i, j + 2)
# 가로선을 연속으로 놓을 수 없으므로 j + 2부터 검사
board[i][j] = 0 # 가로선 없애기
N, M, H = map(int, input().rstrip().split())
# N은 세로선의 개수, M은 가로선의 개수, H는 가로선을 놓을 수 있는 위치의 개수
# 세로선과 가로선의 인덱스는 1부터 시작
if M == 0:
print(0)
exit()
# M이 0일 경우 출발점에서 도착점으로 바로 내려오므로 0 출력 후 종료
# 현재 사다리 구현
board = [[0] * N for _ in range(H)]
for _ in range(M):
# 가로선 정보 입력 받기
a, b = map(int, input().rstrip().split())
board[a - 1][b - 1] = 1
# 사다리에 가로선(왼쪽 끝자락)이 있으면 1, 없으면 0
# 가로선은 왼쪽 끝자락만 표시한다.
ans = 4
# 최소 추가선 개수
dfs(0, 0, 0)
if ans > 3:
ans = -1
print(ans)
코드 설명
1. 사다리 게임의 판을 구현한 2차원 배열 board를 생성한다.
+ board[i][j]가 1이면 i번째 점선과 j번째 세로선의 교점과 i번째 점선과 j+1번째 세로선의 교점을 각각 가로선의 왼쪽 끝, 오른쪽 끝으로 하는 가로선이 존재한다.
+ 우리가 사용하는 board의 점선과 세로선은 0번부터 시작한다.
2. ans는 문제 조건을 만족하기 위해 필요한 가로선의 개수이다.
+ 초기 값을 4로 설정한다. (ans보다 작은 개수로 업데이트 해야 하므로)
+ 모든 경우의 수를 검사해도 조건을 만족하는 경우가 없다면 -1로 변경하여 출력한다.
3. check 함수는 board의 세로선들을 하나씩 검사하여 i번 세로선 상단에서 출발하여 하단까지 왔을 때 i번 세로선 위에 있는지를 검사한다.
4. dfs 함수는 (0, 0)부터 가로선을 추가할 수 있는 모든 인덱스를 검사하여 추가하고, 다음으로 추가할 수 있는 인덱스를 dfs 인자에 넣고 자신을 다시 호출한다. (재귀)
4-1. check 함수를 호출하여 현재 상태가 문제 조건에 맞는 상태라면 현재까지 추가한 가로선 수와 ans값을 비교하여 업데이트하고 함수를 종료한다.
4-2. 추가한 가로선의 개수가 3개이거나 이전 ans값보다 크다면 더이상 볼 필요가 없으므로 함수를 종료한다.
'Algorithm Problems > 완전 탐색' 카테고리의 다른 글
[백준/Python] 10971번: 외판원 순회 2 (3) | 2023.09.01 |
---|---|
[백준/Python] 14620번: 꽃길 (2) | 2023.08.31 |
[백준/python] 15663번: N과 M (9) (2) | 2023.08.08 |
[백준/python] 1107번: 리모컨 (2) | 2023.08.07 |
[백준/python] 9963번: N-Queen (2) | 2023.08.04 |