Algorithm/acmicpc.net

백트래킹?

winney916 2022. 1. 9. 13:56
728x90

#15663번 N과M (9) https://www.acmicpc.net/problem/15663

 

15663번: N과 M (9)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

비슷한 유형의 문제를 연달아 풀고 있는 중이다.

N, M = map(int, input().split())
nums = sorted(list(map(int, input().split())))

output = []
visited = [False]*N


def solve(depth, n, m):
    if depth == m:
        r = ' '.join(map(str, output))
        print(r)
        return
    overLap = 0
    for i in range(n):
        if not visited[i] and nums[i] != overLap:
            output.append(nums[i])
            visited[i] = True
            overLap = nums[i]
            solve(depth+1, n, m)
            visited[i] = False
            output.pop()


solve(0, N, M)

 

이 문제는 그래프 탐색을 기반으로 한다. 2개의 순열을 만들 때는 깊이가 2인 깊이우선탐색을 한다고 생각하면 될 것 같다.

 

이 문제에서 헷갈렸던 점은 출력되는 순열이 중복되어선 안된다는 부분이다.

 

첫 번째 시도에서는 리스트를 만들어서 출력값들을 저장하고 in을 통해서 점검하는 방식을 택했다.

역시나 시간초과

in은 리스트 내의 모든 요소들과 비교를 진행하기 때문에 대부분의 연산에서 O(리스트의 길이)만큼의 시간복잡도가 생긴다. ( O(n) )

 

검색을 통해 조금 더 현명한 방법을 찾았다.

 

1) 숫자 리스트는 기본적으로 정렬한 채로 진행한다.

2) 때문에 같은 수는 연달아 존재한다. [ 1, 1, 2, 2 ]...

3) 그러므로 이전에 나온 수만 저장한 뒤 그 수와 같은 경우만 제외해주면 된다.

 

코드를 재사용하다보니 리스트를 정렬했다는 사실을 까먹은 채로 진행한게 흠이었다.

되도록이면 처음부터 다시 짜는게 좋을 듯 하다.

'Algorithm > acmicpc.net' 카테고리의 다른 글

다음수열, 이전수열  (0) 2022.01.13
백트래킹 : M과 N, 순열  (0) 2022.01.11
백트래킹 : 재귀를 활용한  (0) 2022.01.06
브루트포스 : 때론 조건을  (0) 2022.01.04
브루트포스 : 이제 좀 깊이가 생기는  (0) 2022.01.03