728x90
문제 보기
이 문제는 시뮬레이션 문제이다.
문제를 읽고 어떤 알고리즘을 사용해야 할지 바로 떠오르지 않았다. 10분 넘게 고민하여도 도저히 생각이 안 났다. 완전 탐색을 하면 경우의 수가 너무 많아서 시간 초과가 날 것 같았지만 다른 방법이 떠오르지 않았다. 운이 좋은건지는 모르겠지만 정답은 완전 탐색이었다.
[ 케이스 분류]
문제에서 요구하는 정답이 1, 2, 3 혹은 -1(추가 x, 추가 4개 이상)이기 때문에 5가지로 분류하였다.
1. 가로선 추가 x
2. 가로선 1개 추가
3. 가로선 2개 추가
4. 가로선 3개 추가
5. 그 외
[ 가로선 추가 관리 ]
가로선을 추가하기 위해서 가로선을 추가할 수 있는 구간을 따로 저장하였다. 저장한 구간에서 파이썬 내장 함수 combination을 사용하여 1, 2, 3개를 고르는 모든 경우의 수를 구하였고 인접한 지역에 가로선이 있는지 확인한 후 조건을 만족한다면 가로선을 추가하였다.
[ 사다리 이동 ]
사다리는 2차원 배열을 활용하였으며 0과 1의 값을 가지고 있다. 1의 값을 가지는 경우는 오른쪽과 연결되어 있다고 생각하면 된다. 예를 들어서 현재 위치가 i, j일 때는 arr [i + 1][j]와 arr [i +1][j - 1]을 확인하면 된다. arr [i + 1][j] 값이 1이면 오른쪽으로 이동, arr [i + 1][j - 1]이 1이면 왼쪽으로 이동한다.
코드
import sys
from itertools import combinations
# 각 열을 움직였을때 결과 확인
def move():
for i in range(1, N + 1):
index = [0, i] # 출발시 가로, 세로
while index[0] < H:
if connect[index[0] + 1][index[1]] == 1: # 오른쪽 이동
index[1] += 1
elif index[1] - 1 >= 0 and connect[index[0] + 1][index[1] - 1] == 1: # 왼쪽으로 이동
index[1] -= 1
index[0] += 1
if index[1] != i:
return 0
return 1
# 인접 체크
def check(arr1, arr2):
if arr1[0] == arr2[0]:
if abs(arr1[1] - arr2[1]) == 1:
return True
return False
# 가로선 추가 상황 구현
def find():
if M == 0 or move(): # 이미 구현된 상황
return 0
else:
# 1개 추가로 가능한 상황
for i in range(len(add)):
row, col = add[i]
connect[row][col] = 1
if move():
return 1
else:
connect[row][col] = 0
# 2개 추가로 가능한 상황
order = list(combinations(add, 2))
for i in range(len(order)):
if check(order[i][0], order[i][1]): # 인접 확인
continue
connect[order[i][0][0]][order[i][0][1]] = 1
connect[order[i][1][0]][order[i][1][1]] = 1
if move():
return 2
else:
connect[order[i][0][0]][order[i][0][1]] = 0
connect[order[i][1][0]][order[i][1][1]] = 0
# 3개 추가로 가능한 상황
order = list(combinations(add, 3))
for i in range(len(order)):
if check(order[i][0], order[i][1]) or check(order[i][0], order[i][2]) or check(order[i][1], order[i][2]):
continue
connect[order[i][0][0]][order[i][0][1]] = 1
connect[order[i][1][0]][order[i][1][1]] = 1
connect[order[i][2][0]][order[i][2][1]] = 1
if move():
return 3
else:
connect[order[i][0][0]][order[i][0][1]] = 0
connect[order[i][1][0]][order[i][1][1]] = 0
connect[order[i][2][0]][order[i][2][1]] = 0
# 나머지 상황
return -1
if __name__ == "__main__":
# input
N, M, H = map(int, sys.stdin.readline().split())
line = [list(map(int, sys.stdin.readline().split())) for _ in range(M)] # 가로선의 정보
connect = [[0] * (N + 1) for _ in range(H + 1)] # 전체 연결 정보
# line 정보 -> connect 반영
for i in range(len(line)):
connect[line[i][0]][line[i][1]] = 1
# 가로선 추가 가능한 영역 찾기
add = []
for i in range(1, H + 1):
for j in range(1, N):
if not (connect[i][j - 1] or connect[i][j] or connect[i][j + 1]):
add.append([i, j])
print(find())
728x90
'알고리즘 풀이 > 백준' 카테고리의 다른 글
[ 백준 2493 ] 탑 - Python (4) | 2020.07.02 |
---|---|
[ 백준 1963 ] 소수 경로 - Python (2) | 2020.06.30 |
[ 백준 9446 ] 텀 프로젝트 - Python (0) | 2020.06.16 |
[ 백준 17144 ] 미세먼지 안녕! - Python (2) | 2020.06.15 |
[ 백준 9252 ] LCS 2 - Python (0) | 2020.06.14 |