알고리즘 입문 수업을 듣고 중요한 내용을 정리했습니다.
개인 공부 후 자료를 남기기 위한 목적이므로 내용 상에 오류가 있을 수 있습니다.
문제
[합이 같은 부분집합(DFS)]
N개의 원소로 구성된 자연수 집합이 주어지면, 이 집합을 두 개의 부분집합으로 나눈다. 이 때, 두 부분집합의 원소를 모두 더한 값이 서로 같으면 "YES"를 출력하고 그렇지 않으면 "NO"를 출력하는 프로그램을 작성하시오.
참고로, 둘로 나뉘는 두 부분집합은 서로소 집합이며 두 부분집합을 합하면 입력으로 주어지는 원래의 집합이 되어야 한다. 예를 들면, {1, 3, 5, 6, 7, 10}의 집합이 입력되면 {1, 3, 5, 7} = {6, 10}으로 두 부분집합의 합이 모두 16인 경우가 존재한다.
*입력 설명
첫 번째 줄에 자연수 N(1 ≤ N ≤ 10)이 주어진다.
두 번째 줄에 집합의 원소가 N개 주어진다. (단, 각 원소는 중복되지 않음)
*출력 설명
첫 번째 줄에 "YES" 또는 "NO"를 출력한다.
풀이(Python)
답안
import sys
sys.stdin = open('AA/input_46.txt', 'rt')
def DFS(L, sum):
if sum > total//2:
return
if L == n:
if sum == (total - sum):
print("YES")
sys.exit(0)
else:
DFS(L+1, sum+a[L])
DFS(L+1, sum)
if __name__=="__main__":
n = int(input())
a = list(map(int, input().split()))
total = sum(a)
DFS(0, 0)
print("NO")
# 출력 : YES
input_46.txt(입력)
6
1 3 5 6 7 10
중요내용
- DFS() 함수의 인자 L은 리스트 a의 인덱스 번호를 의미한다.
- DFS() 함수의 인자 sum은 자신이 만든 부분집합 원소의 총합을 의미한다.
- DFS(L+1, sum+a[L]) 코드는 리스트 a의 인덱스 번호가 L인 벨류 값을 부분집합의 원소로 사용하겠다는 의미이다.
- DFS(L+1, sum) 코드는 리스트 a의 인덱스 번호가 L인 벨류 값을 부분집합의 원소로 사용하지 않겠다는 의미이다.
- sys.exit(0)는 해당 코드가 돌아가는 프로그램을 종료시키는 코드이다.
- if sum > total // 2 는 해당 프로그램의 시간 복잡도를 개선하기 위한 코드이다.
- 즉, total을 2로 나눈 몫보다 sum의 값이 커지면 결국 문제에서 원하는 결과(YES)를 얻지 못하기 때문에 나머지 탐색을 할 필요가 없다.
- 따라서 if절의 조건이 sum > total // 2인 경우에는 return을 사용하여 재귀함수(DFS() 함수)를 종료시키고, 불필요한 탐색을 방지하여 시간 복잡도를 개선하는 것이다.
'알고리즘' 카테고리의 다른 글
Algorithm - 중복순열 구하기(DFS) (0) | 2021.12.19 |
---|---|
Algorithm - 바둑이 승차(DFS) (0) | 2021.12.17 |
Algorithm - 부분집합 구하기(DFS) (0) | 2021.12.16 |
Algorithm - 이진트리 순회(DFS : Depth First Search) (0) | 2021.12.16 |
Algorithm - 재귀함수를 활용한 이진수 출력 (0) | 2021.12.14 |
댓글