티스토리 뷰
목차
문제
수열 A가 주어졌을 때, 그 수열의 증가하는 부분 수열 중에서 합이 가장 큰 것을 구하는 프로그램을 작성하시오.
예를 들어, 수열 A = {1, 100, 2, 50, 60, 3, 5, 6, 7, 8}인 경우에 합이 가장 큰 증가하는 부분 수열은
A = {1, 100, 2, 50, 60, 3, 5, 6, 7, 8} 이고, 합은 113이다.
입력
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.
둘째 줄에는 수열 A를 이루고 있는 $A_i$가 주어진다. $(1 ≤ A_i ≤ 1,000)$
출력
첫째 줄에 수열 A의 합이 가장 큰 증가하는 부분 수열의 합을 출력한다.
풀이
이 문제는 쓰여있는 대로 주어진 수열의 증가하는 부분수열 중 합이 최대인 경우를 찾는 것이다.
예를 들어 [1, 100, 2, 50, 60, 3, 5, 6, 7, 8]이라는 수열에서 증가하는 수열이란
[1, 2, 50, 60], [1, 2, 3, 5, 6, 7, 8]과 같은 수열을 말한다. 이 중 합이 가장 큰 수열을 찾아 그 합을 출력하면 된다.
문제를 푸는 알고리즘을 말로 풀어 설명하면 대략 다음과 같은 과정을 거친다.
- DP리스트 초기화
가장 먼저 'dp'리스트를 만들어 주어진 수열을 그대로 저장한다. 이렇게 하는 이유는 각 숫자 하나만으로 이루어진
부분 수열의 합이 자기 자신이기 때문이다. - 이중 반복문을 이용한 탐색
이어서 각 숫자를 하나씩 순회하면서 그 숫자를 마지막으로 하는 증가 부분 수열 중 최대 합을 'dp'에 저장해야 한다.
이를 위해- 현재 숫자보다 앞의 숫자들을 모두 확인하고
- 현재 숫자보다 작은 숫자가 있다면 그 숫자까지의 최대 증가 부분 수열의 합과 현재 숫자를 합한 값을
현재 위치의 'dp'값과 비교해 큰 값으로 갱신한다. - 이런 식으로 모든 숫자를 확인하면 그 자체로 해당 숫자까지의 최대 합을 저장한 리스트가 된다.
- 'dp'리스트 중 최댓값을 출력한다.
주어진 예시[1, 100, 2, 50, 60, 3, 5, 6, 7, 8]에 따라 문제를 풀면 다음과 같은 과정을 거치게 된다.
- dp[0]는 1이다.
- 두 번째 숫자 100에 대해서는 앞에 그보다 작은 1이 있으므로, 이를 더한 101과 100중 더 큰 값인 101을 dp[1]에 저장한다.
- 세 번째 숫자 2에 대해서는 앞에 숫자 1과 100이 있으므로, 작은 값인 1을 더해 3으로 갱신한다.
- 네 번째 숫자 50에 대해서는 같은 논리로 1, 2를 더해 53을 저장한다.
- 다섯 번째 숫자 60에 대해서든 1, 2, 50을 더한 113을 저장한다.
- 이런 식으로 리스트의 끝까지 반복한다.
- 순회가 끝난 리스트의 최댓값은 113이므로, 해당 숫자를 출력한다.
계속해서 이 알고리즘을 코드로 표현해보자.
Python
import sys
N = int(sys.stdin.readline().rstrip())
lst = list(map(int, sys.stdin.readline().split()))
dp = lst.copy()
for i in range(N):
for j in range(i):
if lst[i] > lst[j]:
dp[i] = max(dp[i], dp[j] + lst[i])
print(max(dp))
설명에 비해 코드가 간단하다.
동적계획법 문제는 답을 보면 쉽지만 거기까지 다다르기가 수월하지만은 않은 것 같다.
기존의 생각 방법을 벗어난 사고를 해야 하기 때문인지도 모른다.
어쨌거나 가장 간단한 방법으로 11055번, 가장 큰 증가하는 부분 수열 문제를 풀어보았다.
끝!
'Algorithm > Dynamic Programming' 카테고리의 다른 글
[Python]2294번, 동전 2 (0) | 2023.11.08 |
---|---|
[Python]11722번, 가장 큰 증가하는 부분 수열 (0) | 2023.11.04 |
[Python]14501번, 퇴사 (0) | 2023.10.21 |
[Python]1463번, 1로 만들기 (0) | 2023.10.17 |
[Python]9095번, 1, 2, 3 더하기 (0) | 2023.10.12 |
[Python]2839번, 설탕 배달 (0) | 2023.10.11 |
- Total
- Today
- Yesterday
- 야경
- BOJ
- 세계여행
- 유럽여행
- 스프링
- 세모
- 중남미
- 알고리즘
- a6000
- 칼이사
- 기술면접
- 지지
- 여행
- RX100M5
- 남미
- java
- Backjoon
- spring
- 동적계획법
- Algorithm
- 맛집
- 자바
- 면접 준비
- 리스트
- 백준
- 스트림
- 세계일주
- 파이썬
- Python
- 유럽
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |