isPowerfulBlog
[Solved] BOJ: 11053 | 가장 긴 증가하는 부분 수열 본문
문제
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하기
입력과 출력
입력
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.
둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)
출력
첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.
문제 해결 요약
- 수열의 길이를 카운트하는 dp 테이블 생성(카운트값)
- 전체 순열을 순회하면서 i번째 수에 대해
- i-1부터 첫번째 인덱스까지 역으로 순회하며
- i번째 수보다 크다면 해당 수의 카운트값+1로 i번째 카운트값을 갱신
코드 설명
import 및 입력받기
-
import sys
input = sys.stdin.readline
n = int(input())
seq = [0]
seq += list(map(int, input().split()))
- 수열의 길이 n과 수열 seq를 입력받음
- 인덱싱 편의를 위해 seq 리스트 맨 처음에 0을 추가하여 인덱스를 1부터 셀 수 있도록 함
dp 테이블 생성
각 수에 대해 카운트값을 저장할 dp 테이블 생성
-
cnt = [0] + [1 for _ in range(n)]
- seq와 인덱스를 맞춰주기 위해 cnt 리스트도 0을 맨 앞에 추가
- 어떤 수이든 기본적으로 cnt값이 최소 1은 되므로 1로 초기화
dp테이블에 카운트값 갱신
수열 전체를 순회,
i번째보다 인덱스가 작은 부분들의 cnt값을 체크하여
i번쨰 cnt값을 갱신
-
for i in range(2, n+1):
j = i-1
while j > 0:
if seq[i] > seq[j]:
cnt[i] = max(cnt[j]+1, cnt[i])
j -= 1
else:
j -= 1
- 수열의 제일 첫번째 수는 무조건 카운트 값이 1 이므로 1부터 순회할 필요 없음 -> 2부터 순회
- 아까 인덱싱 편의를 위해 리스트 앞에 의미없는 0을 추가했으므로 n+1 전까지 순회
- i보다 인덱스가 작은 부분들을 역으로 순회하면서
- cnt값 + 1이 i번째 cnt값보다 크다면
- i번째 cnt 값을 갱신
dp 테이블의 최댓값 출력
print(max(cnt))
- dp 테이블에서 max값을 출력하는게 답
전체 코드
import sys
input = sys.stdin.readline
n = int(input())
seq = [0]
seq += list(map(int, input().split()))
cnt = [0] + [1 for _ in range(n)]
for i in range(2, n+1):
j = i-1
while j > 0:
if seq[i] > seq[j]:
cnt[i] = max(cnt[j]+1, cnt[i])
j -= 1
else:
j -= 1
print(max(cnt))
- 근데 사실 j 돌릴때 역으로 안 하고 1부터 i보다 작을 때까지 while문 돌려도 됨, 역으로 하면 갱신 횟수가 좀 더 적을 듯
'Algorithm' 카테고리의 다른 글
[Solved] BOJ: 4963 | 섬의 개수 (0) | 2023.02.02 |
---|---|
[Solved] BOJ: 2630 | 색종이 만들기 (0) | 2022.12.06 |
[Algorithm] Dynamic Programming (1) | 2022.11.24 |
[Solved] BOJ: 2467 | 용액 (0) | 2022.11.20 |
[Solved] BOJ: 1389 | 케빈 베이컨의 6단계 법칙 (0) | 2022.11.15 |