[파이썬] 백준 15684번 사다리 조작

작성:

백준 #15684 사다리 조작


  • Python 시간 초과, PyPy 통과
# index 1부터 시작
# 사다리는 연속하거나 접하면 안 된다.

# 출력: i번 세로선의 결과가 i가 나오는 최소 가로선 개수
#     정답이 3보다 크면 -1 출력, 불가능하면 -1 출력

# 세로선 최대 10개, 가로선 위치 최대 30
# 300 * (210 * 210C2 * 210C3)
# 좀 더 효율적인 방법을 찾아보자.
# 일단 조합으로 가능한 가로선마다 구해서 해보긴 해보자.

# 세로선 하나하나가 각각의 열이 되도록 행렬을 만든다.
#   H x (N + 2, 양 끝)
# 1. 가능한 가로선을 구하는 조합
# 2. 처음부터 끝까지 세로선이 해당 숫자로 가는지 체크하는 함수
# 가능한 때 곧바로 최솟값을 출력한다.

def combi(arr, start, r):
    for i in range(start, len(arr) - r + 1):
        if r == 1:
            yield [arr[i]]
        else:
            for j in combi(arr, i+1, r-1):
                is_possible = True
                for y, x in j:
                    if y == arr[i][0] and x-1 <= arr[i][1] <= x+1:
                        is_possible = False
                        break
                if not is_possible: continue
                yield [arr[i]] + j

def check(N, H):
    for i in range(1, N+1):
        y, x = 0, i
        while y < H:
            if field[y][x][0]: x -= 1
            elif field[y][x][1]: x += 1
            y += 1
        if x != i: return False
    return True

N, M, H = map(int, input().split())
field = [[[0,0] for i in range(N+2)] for j in range(H)]
candis = []
result = float('inf')

for _ in range(M):
    a, b = map(int, input().split())
    field[a-1][b][1] = 1
    field[a-1][b+1][0] = 1

for i in range(H):
    for j in range(1, N):
        if field[i][j][0] or field[i][j+1][0] or field[i][j+1][1]: continue
        else: candis.append((i,j))

if check(N, H):
    print(0)
else:
    found = False
    for i in range(1, 4):
        for case in combi(candis, 0, i):
            for y, x in case:
                field[y][x][1] = 1
                field[y][x+1][0] = 1
            if check(N, H):
                found = True
                print(i)
                break
            for y, x in case:
                field[y][x][1] = 0
                field[y][x+1][0] = 0
            if found: break
        if found: break
    else:
        print(-1)

댓글남기기