일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 읽기
- English
- 3줄정리
- 사이드
- 개발자
- 잡생각
- 영어원서읽기
- 월간
- 30분
- 쓰릴오브파이트
- Problem Solving
- 운동
- 영어공부
- 링피트
- 프로젝트
- Daily Challenge
- 리얼 클래스
- leetcode
- 파비최
- FIT XR
- realclass
- 만화도
- 10분
- 매일
- Writing
- 미드시청
- 스탭퍼
- 화상영어
- 괜찮음
- 뭐든
Archives
- Today
- Total
파비의 매일매일 공부기록
5.4 부분집합의 합 구하기 - DP 본문
이번에는 지난번에 구현했던 재귀 호출을 DP로 바꿔본다.
DP의 접근 법은 상향식으로 문제를 풀어가면서 중간결과를 2차원 배열에 저장하는 것이다.
2차원 배열에 저장될 값은 각 집합의 첫(i+1) 개의 원소로 구성된 집합에 대해서 합이 j(0 <=j <=X)인 부분집합이 있는지에 대한 참/거짓의 값이다.
첫 번째 열은 무조건 참이 됨. 공집합인 부분집합 원소의 합은 언제나 0이기 때문.
첫 번째 행의 경우 집합과 j의 값이 같은 경우만 True, 다르면 False 값을 넣는다.
그 외의 조건은 다음과 같다.
1. 바로 위쪽 셀이 T면, 해당 셀도 T.
2. 그 외에는 (i-1, j-v) 셀의 값을 (i, j)로 복사.
위의 조건을 코드로 옮기면 다음과 같다.
def solve_dp(ar, n, x):
subsum = [[False for _ in range(n)] for __ in range(x + 1)]
for i in range(n):
subsum[i][0] = True
for j in range(1, x + 1):
if ar[0] == j:
subsum[0][j] = True
else:
subsum[0][j] = False
for i in range(1, n):
v = ar[i]
for j in range(1, x + 1):
if j < v:
subsum[i][j] = subsum[i - 1][j]
elif subsum[i - 1][j]:
subsum[i][j] = True
else:
subsum[i][j] = subsum[i - 1][j - v]
return subsum[n - 1][x]
if __name__ == '__main__':
ar = list(map(int, input().split()))
n = len(ar)
x = int(input())
print(solve(ar, n, x))
생각보다 로직이 복잡하다. 기존에 했던 것들에 비해.
j-v 값을 가져오는 게 좀 핵심인 듯..
반응형
'Study > Algorithm 문제풀이' 카테고리의 다른 글
5.5 최장 공통 부분 수열 길이 구하기 - 메모전략 (0) | 2021.09.13 |
---|---|
5.5 최장 공통 부분 수열 길이 구하기 - 재귀 (0) | 2021.09.12 |
5.4 부분집합의 합 구하기 - 재귀 (0) | 2021.09.10 |
DP 정복 - 5.3 문자열 인터리빙 확인 문제 (0) | 2021.09.08 |
DP 정복 - 5.2 직사각형에서 총 경로 수 구하기 (0) | 2021.09.07 |
Comments