문제
수열 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 |