sm 기술 블로그

137. 11054(가장 긴 바이토닉 부분 수열) 본문

문제/백준_파이썬

137. 11054(가장 긴 바이토닉 부분 수열)

sm_hope 2022. 7. 10. 00:07
import sys
input = sys.stdin.readline

N = int(input())
num = list(map(int,input().split()))
numReverse = num[::-1]

numDpIncrease = [1]*N
numDpDecrease = [1]*N

for i in range(N):
  for j in range(i):
    if num[i] > num[j]:
      numDpIncrease[i] = max(numDpIncrease[i], numDpIncrease[j]+1)
    if numReverse[i] > numReverse[j]:
      numDpDecrease[i] = max(numDpDecrease[i],numDpDecrease[j]+1)

result = [0]*N
for i in range(N):
  result[i] = numDpIncrease[i] + numDpDecrease[N-i-1]-1

print(max(result))

문제요약

가장 긴 바이토닉 부분 수열은?

S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면, 그 수열을 바이토닉 수열

설명

문제에 힌트가 있다.

S1 < S2 < ... Sk-1 < Sk 이 부분과

Sk > Sk+1 > ... SN-1 > SN 이 부분을 따로 생각해보자.

 

S1 < S2 < ... Sk-1 < Sk 이 부분은 0번째 인덱스 부터 증가하는 수열, 

Sk > Sk+1 > ... SN-1 > SN 아 부분은 N번째 인덱스 부터 증가하는 수열. 

 

따라서 

다음과 같이 입력값 | 입력값을 뒤집은 값을 나눈다.

 

수열을 진행하면서 해당 인덱스에서 가장 큰 길이를 가질 수 있는 것을 각각 정의해준다.

 

nomal에 해당 인덱스를 뒤집었기 때문에.

nomal[index] + reverse[N - index -1] 를 해준다면 1번과 2번을 합친 것이된다.

단, index 부분은 두 번 중복으로 수열을 처리했기 때문에 마지막에 -1을 해줘야 한다.

 

N = int(input())
num = list(map(int,input().split()))
numReverse = num[::-1]

값을 입력받고 뒤집어 주었다.

numDpIncrease = [1]*N
numDpDecrease = [1]*N

for i in range(N):
  for j in range(i):
    if num[i] > num[j]:
      numDpIncrease[i] = max(numDpIncrease[i], numDpIncrease[j]+1)
    if numReverse[i] > numReverse[j]:
      numDpDecrease[i] = max(numDpDecrease[i],numDpDecrease[j]+1)

두개의 리스트를 만들고. 

원래 리스트, 뒤집은 리스트에 해당 인덱스에 각각 가장 긴 수열을 계산해 주었다.

result = [0]*N
for i in range(N):
  result[i] = numDpIncrease[i] + numDpDecrease[N-i-1]-1

원래 값과 뒤집은 값을 더해 result를 에 저장해준다. 단, 계산과정 중 중복으로 처리한 부분이 있어 -1을 해준다.

'문제 > 백준_파이썬' 카테고리의 다른 글

139. 9251(LCS)  (0) 2022.07.10
138. 2565(전깃줄)  (0) 2022.07.10
136. 11053(가장 긴 증가하는 부분 수열)  (0) 2022.07.08
135. 2156(포도주 시식)  (0) 2022.07.08
133. 1463(1로 만들기)  (0) 2022.07.04
Comments