본문 바로가기
코딩테스트

99클럽 코테 스터디 32일차 TIL : 백준 11054번, 최장 증가 부분 수열

by fecu 2024. 11. 28.
728x90

 

1. 오늘의 문제

 

보자마자 최장 증가 부분 수열임을 알아지만 푸는데 꽤나 오랜 시간이 걸렸다.

 

자꾸 반례에 걸렸는데, 왜 걸리는지조차 알기가 쉽지 않았다.

 

결국 백준에서 검색을 통해 반례를 찾아보았다.

 

더보기

문제

 

수열 S가 어떤 수 Sk를 기준으로 S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면, 그 수열을 바이토닉 수열이라고 한다.

예를 들어, {10, 20, 30, 25, 20}과 {10, 20, 30, 40}, {50, 40, 25, 10} 은 바이토닉 수열이지만, {1, 2, 3, 2, 1, 2, 3, 2, 1}과 {10, 20, 30, 40, 20, 30} 은 바이토닉 수열이 아니다.

수열 A가 주어졌을 때, 그 수열의 부분 수열 중 바이토닉 수열이면서 가장 긴 수열의 길이를 구하는 프로그램을 작성하시오.

 

입력

 

첫째 줄에 수열 A 크기 N 주어지고, 둘째 줄에는 수열 A 이루고 있는 Ai 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)

 

2. 반례 모음

 

6
1 4 3 2 5 1
답 5

10
1 5 2 1 4 3 4 5 2 1
답 7

2
2 1
답 2

6
1 2 3 3 2 1
답 5

10
10 1 3 5 7 6 3 2 1 10
답 8

11
1 2 3 4 5 1 5 4 3 2 1
답 9

3
1 1 1
답 1

 

3. 코드 구상

 

처음에는 최장 증가 부분 수열의 최대값을 찾고, 그 인덱스 에서 다시 길이를 측정하는 코드를 짰다.

 

그렇게 하자 아래 반례에서 문제가 생겼다.

 

10 / 10 1 3 5 7 6 3 2 1 10

 

이걸 보자마자 인덱스는 필요 없고, 모든 노드에서 길이를 측정해야 한다는 사실을 깨달았다.

 

그래서 원래의 배열에서 순차로 길이를 재고, 배열을 뒤집은 다음 순차로 길이를 잰 다음에 두 값을 합쳐주면 될 것 같았다.

 

4. 코드

 

from sys import stdin
put = stdin.readline

totalNum = int(put())

# 원래 배열과 길이 배열 준비
numsLst = list(map(int, put().split()))
lengths = [1 for _ in range(totalNum)]

# 뒤집은 배열과 뒤집은 길이 배열 준비
numsLstCopy = numsLst.copy()
numsLstCopy.reverse()
lengthsCopy = lengths.copy()

# 증가 부분 수열 길이 측정
for i in range(0, totalNum):
    for j in range(0, i):
        if numsLst[i]>numsLst[j]:
            thisTotal = lengths[j] + 1
            lengths[i] = max(thisTotal, lengths[i])

# 뒤집은 배열의 증가 부분 수열 길이 측정
for i in range(0, totalNum):
    for j in range(0, i):
        if numsLstCopy[i]>numsLstCopy[j]:
            thisTotal = lengthsCopy[j] + 1
            lengthsCopy[i] = max(thisTotal, lengthsCopy[i])
# 원래의 배열 순서로 다시 뒤집어 줌
lengthsCopy.reverse()

# 두 값의 합산값들 중 최고 값을 출력함.
results = []
for x, y in zip(lengths, lengthsCopy):
    results.append(x+y)
print(max(results)-1)

 

5. 느낀점

 

반례가 없으니 오랫동안 헤메었다.

 

실제 코딩 상황에서도 반례를 알 수 없으니 어떤 상황에서 반례가 나오는지 고민해보는 것도 좋은 공부가 아닐까 생각이 들었다.

 

이제 LIS는 거의 마스터 한 듯 하다.

728x90