백트래킹 심화: 부분 수열의 합

2024-11-05 15:05:42 | 조회수 81


4. 심화 예제: 부분 수열의 합 (Subset Sum) 문제 🧩

부분 수열의 합 문제는 백트래킹 기법을 이용하여 부분 집합 중에서 특정 합을 만족하는 부분 집합을 찾는 고급 문제입니다. 이 문제는 최적화와 가지치기 기법을 결합하여 탐색 공간을 줄이면서 효율적으로 해결할 수 있습니다.

풀이 접근:

  • 1️⃣ 배열의 각 요소를 선택하거나 선택하지 않는 방식으로 모든 부분 집합을 탐색합니다.
  • 2️⃣ 현재 부분 집합의 합이 목표를 초과할 경우, 해당 경로는 더 이상 탐색하지 않는 가지치기를 수행합니다.
  • 3️⃣ 목표 합에 도달할 경우 탐색을 종료하고 결과를 출력합니다.
Python 코드 예제:
def subset_sum(arr, target, index=0, current_sum=0, subset=[]):
    # 목표 합에 도달한 경우 부분 집합 출력
    if current_sum == target:
        print(subset)
        return True
    
    # 배열 끝까지 탐색했거나, 목표 초과 시 가지치기
    if index == len(arr) or current_sum > target:
        return False

    # 현재 요소 포함하고 재귀 호출
    subset.append(arr[index])
    if subset_sum(arr, target, index + 1, current_sum + arr[index], subset):
        return True
    
    # 현재 요소 제외하고 다음 요소 탐색 (백트래킹)
    subset.pop()
    return subset_sum(arr, target, index + 1, current_sum, subset)

# 예제 사용
arr = [3, 34, 4, 12, 5, 2]
target = 9
subset_sum(arr, target)
                

설명: subset_sum 함수는 백트래킹을 이용하여 모든 부분 집합을 탐색하고, 목표 합에 도달할 경우 부분 집합을 출력합니다. 현재 요소를 포함하거나 제외하며 모든 경우를 탐색하고, 목표 합을 초과하면 가지치기를 수행하여 탐색을 효율화합니다.

5. 가지치기 기법 심화 🌟

백트래킹에서 가지치기 기법을 잘 활용하면 탐색 공간을 효과적으로 줄여 문제를 빠르게 해결할 수 있습니다. 다음은 부분 수열의 합 문제에서 사용할 수 있는 심화된 가지치기 기법입니다:

  • 1. 정렬 기반 가지치기: 배열을 오름차순으로 정렬한 후, 부분 합이 목표 합을 초과하는 경우 더 이상 탐색하지 않습니다. 예를 들어, 정렬된 배열에서 현재 합과 다음 원소를 포함한 합이 목표를 초과하면 이후 원소를 탐색하지 않고 가지를 쳐서 탐색 속도를 높일 수 있습니다.
  • 2. 제한 조건 기반 가지치기: 문제에 따라, 현재까지 사용된 원소의 합이 목표에 도달하지 못할 경우 탐색을 중단합니다. 예를 들어, 남은 원소의 합이 현재 필요한 합보다 작다면 더 이상 탐색할 필요가 없습니다.

이러한 가지치기 기법을 활용하면 백트래킹 알고리즘의 탐색 시간을 줄이고, 보다 효율적인 탐색을 수행할 수 있습니다.

6. 심화 문제: 서로 다른 조합을 이용한 부분 수열의 합 찾기 ⚙️

부분 수열의 합 문제의 심화 버전으로, 동일한 값을 가진 원소가 포함된 배열에서 특정 합을 만족하는 모든 서로 다른 조합을 찾는 문제를 백트래킹과 가지치기 기법으로 해결할 수 있습니다. 이 문제는 특히 대회나 고급 백트래킹 문제에서 자주 등장합니다.

문제 정의: 주어진 배열에서 목표 합을 만족하는 모든 서로 다른 부분 집합을 구하세요. 예를 들어 배열이 [2, 3, 6, 7]이고 목표 합이 7인 경우, [7][2, 2, 3]과 같은 조합을 찾습니다.

Python 코드 예제:
def unique_combinations(arr, target, index=0, current_sum=0, subset=[]):
    # 목표 합에 도달한 경우 결과 출력
    if current_sum == target:
        print(subset)
        return
    
    for i in range(index, len(arr)):
        # 가지치기: 현재 요소가 목표 초과 시 탐색 중단
        if current_sum + arr[i] > target:
            break

        # 중복 방지 조건 추가
        if i > index and arr[i] == arr[i - 1]:
            continue

        # 요소 추가 후 재귀 호출
        subset.append(arr[i])
        unique_combinations(arr, target, i + 1, current_sum + arr[i], subset)
        subset.pop()  # 백트래킹

# 예제 사용
arr = [2, 3, 6, 7]
arr.sort()
target = 7
unique_combinations(arr, target)
                

설명: unique_combinations 함수는 중복을 피하기 위해 정렬된 배열에서 각 요소를 한 번씩만 포함하며, 현재 부분 합이 목표 합을 초과하면 해당 경로를 가지치기합니다. 이렇게 하면 서로 다른 모든 조합을 효율적으로 찾을 수 있습니다.

이번 글에서는 백트래킹의 고급 기법과 가지치기를 통해 탐색 효율성을 극대화하는 방법을 배웠습니다. 대회급 문제에서 백트래킹을 활용해 최적화하는 기법을 연습해보세요!


백트래킹 심화: 부분 수열의 합 - 알고리즘닷컴 19 개의 글