이 영역을 누르면 첫 페이지로 이동
hoonDEV 블로그의 첫 페이지로 이동

hoonDEV

페이지 맨 위로 올라가기

hoonDEV

BOJ 11054 - 가장 긴 바이토닉 부분 수열

  • 2020.04.03 18:27
  • 알고리즘/문제풀이

문제를 읽고 이해하기

수열 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)

출력

첫째 줄에 수열 A의 부분 수열 중에서 가장 긴 바이토닉 수열의 길이를 출력한다.

예제 입력 1

10 1 5 2 1 4 3 4 5 2 1

예제 출력 1

7

재정의와 추상화

(바이토닉 수열이 무엇인지는 문제에 나와있으니 따로 설명하지 않겠습니다.)

예제 입력을 보면 10 1 5 2 1 4 3 4 5 2 1 의 원소를 가지는 수열의 부분수열 중 가장 긴 바이토닉 수열은 10 1 5 2 1 4 3 4 5 2 1 으로, 1 2 3 4 5 2 1 이다. 따라서 출력이 7이다.

이 예제를 통해 알 수 있듯이, 원소가 서로 인접한지는 상관 없이, 특정 원소 Sk를 기준으로 왼쪽에서 S1 < S2 < ... Sk-1 < Sk 을 만족하고 오른쪽에서 Sk > Sk+1 > ... SN-1 > SN를 만족하는 부분 수열 중 가장 긴 것을 찾는 것이 문제이다.

따라서 왼쪽과 오른쪽을 나누어 각각 동적 계획법(DP)를 적용한다. 점화식은 아래와 같다.

// 1 <= i < n
// 0 <= k <= i - 1
// arr[i] > arr[k]에 대해서
dp[i][왼쪽] = max(dp[k][왼쪽] + 1, dp[i][왼쪽])

// 0 <= i <= n - 2
// i + 1 <= k < n
// arr[i] > arr[k]에 대해서
dp[i][오른쪽] = max(dp[k][오른쪽] + 1, dp[i][오른쪽]);
  • dp[i][방향] : i번째 원소에 대해 특정 방향에서 바이토닉 수열의 조건을 만족하는 부분 수열 중 가장 긴 수열의 길이

위 과정을 통해 왼쪽과 오른쪽 방향 각각에서 바이토닉 수열의 조건을 만족하는 가장 긴 수열의 길이를 찾았다면, 왼쪽에서의 값과 오른쪽에서의 값을 더한 후 + 1 한 것이 i번째 원소에 대해 양방향에서 바이토닉 수열의 조건을 만족하는 부분 수열 중 가장 긴 수열의 길이이다.

for (int i = 0; i < n; i++)
    values.push(dp[i][왼쪽] + dp[i][오른쪽] + 1);

코드 작성

#include <iostream>
#include <queue>
#include <utility>
using namespace std;

int arr[1001];
int dp[1001][2];
priority_queue<int> values;

int main() {
    int n;
    cin >> n;

    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }

    for (int i = 1; i < n; i++) {
        for (int k = i - 1; k >= 0; k--) {
            if (arr[i] > arr[k]) {
                dp[i][0] = max(dp[k][0] + 1, dp[i][0]);
            }
        }
    }

    for (int i = n - 2; i >= 0; i--) {
        for (int k = i + 1; k < n; k++) {
            if (arr[i] > arr[k]) {
                dp[i][1] = max(dp[k][1] + 1, dp[i][1]);
            }
        }
    }

    for (int i = 0; i < n; i++)
        values.push(dp[i][0] + dp[i][1] + 1);

    cout << values.top();

    return 0;
}

'알고리즘 > 문제풀이' 카테고리의 다른 글

BOJ 15650 - N과 M (2) 문제풀이  (0) 2020.04.03
BOJ 15649 - N과 M (1) 문제풀이  (0) 2020.04.03
BOJ 1992 - 쿼드트리 문제풀이  (0) 2020.04.03
BOJ 6010 - Music Notes 문제풀이  (0) 2020.04.02
BOJ 1920 - 수 찾기 문제풀이  (0) 2020.04.01

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • BOJ 15650 - N과 M (2) 문제풀이

    BOJ 15650 - N과 M (2) 문제풀이

    2020.04.03
  • BOJ 15649 - N과 M (1) 문제풀이

    BOJ 15649 - N과 M (1) 문제풀이

    2020.04.03
  • BOJ 1992 - 쿼드트리 문제풀이

    BOJ 1992 - 쿼드트리 문제풀이

    2020.04.03
  • BOJ 6010 - Music Notes 문제풀이

    BOJ 6010 - Music Notes 문제풀이

    2020.04.02
다른 글 더 둘러보기

정보

hoonDEV 블로그의 첫 페이지로 이동

hoonDEV

  • hoonDEV의 첫 페이지로 이동

검색

메뉴

  • 홈
  • 태그

카테고리

  • 분류 전체보기 (91)
    • 일상 (13)
      • 후기 (1)
      • 계획 (11)
    • 공지사항 (1)
    • 알고리즘 (54)
      • 문제풀이 (53)
      • 이론 (1)
    • 공부 (19)
      • React (0)
      • Angular (5)
      • Java (3)
      • C, C++ (3)
      • JavaScript (6)
      • WEB (2)
    • 디자인 (1)
      • UI, UX (1)
    • 개발 (0)
      • boom (0)

최근 글

인기 글

댓글

공지사항

아카이브

태그

  • 이분탐색
  • javascript
  • 문제풀이
  • 그리디
  • dp
  • 백준
  • 알고리즘
  • es6

나의 외부 링크

정보

훈개발자의 hoonDEV

hoonDEV

훈개발자

블로그 구독하기

  • 구독하기
  • RSS 피드

방문자

  • 전체 방문자
  • 오늘
  • 어제

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. © 훈개발자. Designed by Fraccino.

티스토리툴바