본문 바로가기
코딩테스트 파이썬/다이나믹

11053 가장 긴 증가하는 부분수열( LIS) (재시도 - 0)

by 백엔드 개발자 2021. 7. 7.

문제

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)

출력

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.

 

전에 문제중 LIS 활용하는 문제가 있었는데 까먹어 버렸다 ㅜㅠ

 

키워드 : 이 알고리즘을 몰라서 dp 안쓰고 풀려했는데 그냥 다시 익히는게 낫다고 생각해서 

빠르게 봤다

 

핵심 방법은 수열을 담은 배열과 dp 테이블을 우선 따로둔다. 

dp테이블은 우선 1로 초기화한다. dp[0]에 어차피 1을 넣어야 되서 

 

dp[i]를 i번째까지 가장 긴 부분수열의 개수라고 가정했을 때,

이전원소와 현재 인덱스번호의 원소를 비교해서 이전이 더작으면 

현재 dp테이블의 개수(dp[i]) 와 이전dp[j]+1중 최댓값을 구해서 집어넣는다.

이걸 이중for문을 쓰는데 그이유는 현재 인덱스까지 이전원소들이 다 다르고

이전원소들중 부분수열의 개수가 가장 큰것을 가져와야 하기 때문이다.

 

풀이 :

#n입력
n=int(input())
#수열 입력
arr=list(map(int,input().split()))
dp=[1]*(n)

#LIS알고리즘 사용
#2 for문으로 이전arr 원소가 현재arr 원소보다 작을경우
#이전 원소의 dp+1과 현재 dp값중 최대값을 넣는다.
#처음에는 전부1이므로 어떤 이전원소든 그 값+1로 들어가겠지만
#이전원소중 가장 큰값이 결국 들어가게 되어있다.
for i in range(n):
   for j in range(i): # 여기서 현재 원소인 i전까지만 for문을 내부로 돌림으로서 이전원소들중 작으면서 가장 부분수열이 많은 개수를 현재 dp[i]에 저장한다.
     if arr[i]>arr[j]:
       dp[i]=max(dp[i],dp[j]+1)

print(max(dp))

 

'코딩테스트 파이썬 > 다이나믹' 카테고리의 다른 글

9465 스티커 (재시도 -0)  (0) 2021.07.08
1912 연속합 (재시도 -0)  (0) 2021.07.08
11727 2xn 타일링 2  (0) 2021.07.07
11726 2xn 타일링  (0) 2021.07.07
9095 123 더하기  (0) 2021.07.06