[c++] BOJ 11054 :: κ°€μž₯ κΈ΄ 바이토닉 λΆ€λΆ„ μˆ˜μ—΄

λ‚œμ΄λ„ : κ³¨λ“œ 3

κ±Έλ¦° μ‹œκ°„ : 50λΆ„

문제

문제 λ°”λ‘œκ°€κΈ°

 

풀이

 

μ²˜μŒμ— 풀이λ₯Ό μ΄μƒν•˜κ²Œ μƒκ°ν•΄μ„œ O(n^3)의 완전탐색 ν˜Ήμ€ DPλ₯Ό μ‚¬μš©ν•˜λŠ” 법을 μƒκ°ν•˜κ³  μžˆμ—ˆλ‹€. κ·ΈλŸ¬λ‹€κ°€ 생각을 λ‹€μ‹œ ν•΄λ³΄λ‹ˆ μ‰½κ²Œ ν’€ 수 μžˆλŠ” 방법이 μžˆμ–΄ 20λΆ„λ§Œμ— ν’€κ²Œ λ˜μ—ˆλ‹€. μ—­μ‹œ μ²˜μŒμ— 풀이λ₯Ό μ£Όμ„μœΌλ‘œ μ­‰ 적어본 ν›„ 예제λ₯Ό ν…ŒμŠ€νŠΈ 해보고 μˆ˜ν–‰ν•˜λŠ” 것이 제일 μ •ν™•ν•˜κ³  μ•Œλ§žμ€ 방법인 λ“― ν•˜λ‹€.

 

 

μž…λ ₯의 λ²”μœ„λŠ” 10^3둜 그닀지 높은 νŽΈμ€ μ•„λ‹ˆμ—ˆμ§€λ§Œ, 완전탐색 μ‹œ O(n^3)이 κ±Έλ¦¬λ―€λ‘œ μΆ©λΆ„νžˆ μ‹œκ°„μ΄ˆκ³Όκ°€ λ‚˜μ˜¬ 수 μžˆλŠ” λ²”μœ„μ˜€λ‹€. λ˜ν•œ 각 숫자의 λ²”μœ„λ„ μ΅œλŒ€ 10^3μ΄λ―€λ‘œ 숫자λ₯Ό ν•˜λ‚˜μ”© λ‚΄λ €κ°€λ©° / μ˜¬λ €κ°€λ©° ν‘ΈλŠ” 완전탐색 λ˜ν•œ λΆˆκ°€λŠ₯ν–ˆλ‹€.

예제의 힌트λ₯Ό λ³΄λ‹ˆ 연속적이지 μ•Šμ€ μˆ˜μ—΄μ˜ 흐름도 κ°€λŠ₯ν–ˆκ³ , κ·Έλ ‡λ‹€λ©΄ 각 μˆ«μžκ°€ λ³΄μœ ν•˜κ³  μžˆλŠ” max 값을 κ°±μ‹ μ‹œν‚€λŠ” μ‹μœΌλ‘œ λ™μž‘ν•˜λ©΄ λ˜μ§€ μ•Šμ„κΉŒ μƒκ°ν–ˆλ‹€.

  • μˆ˜μ—΄μ΄ 였λ₯΄λŠ” ꡬ간을 λ”°λΌκ°€λ©΄μ„œ κ°€μ§ˆ 수 μžˆλŠ” max lengthλ₯Ό μ €μž₯ν•œλ‹€.
    • ex_) 1 2 4 3 μ—μ„œ 3κ³Ό 4λŠ” λͺ¨λ‘ 1 2 4 3 / 1 2 4 3 κ³Ό 같이 3 길이의 μ˜€λ¦„μ°¨μˆœ μˆ˜μ—΄μ„ κ°€μ§ˆ 수 μžˆμœΌλ―€λ‘œ λ‘˜ λ‹€ max lengthκ°€ 3이닀.
  • 였λ₯΄λŠ” ꡬ간은 μ—¬λŸ¬ 경우의 μˆ˜κ°€ λ‚˜μ˜¬ 수 μžˆμœΌλ―€λ‘œ μž¬κ·€ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ κ΅¬ν˜„ν•œλ‹€.
  • μˆ˜μ—΄μ˜ λ°˜λŒ€νŽΈμ—μ„œ 였λ₯΄λŠ” ꡬ간 (μ‹€μ œλ‘œλŠ” λ‚΄λ¦Όμ°¨μˆœ ꡬ간)을 λ”°λΌκ°€λ©΄μ„œ max lengthλ₯Ό μ €μž₯ν•œλ‹€.
  • 두 length의 합이 max인 것을 κ³ λ₯Έ ν›„ 1을 λΉΌμ€€λ‹€.
    • 1 5 2 1 4 3 4 5 2 1 μ—μ„œ 5κ°€ 가진 lengthλŠ” μ™Όμͺ½μ—μ„œ 온 5와 였λ₯Έμͺ½μ—μ„œ 온 3이닀. λ”°λΌμ„œ 5 μžμ‹ μ΄ λ‘λ²ˆ 카운트 λ˜μ—ˆμœΌλ―€λ‘œ 1을 λΉΌμ€€ 것이 정닡이닀.

 

μ½”λ“œ

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> vec; // μˆ˜μ—΄
vector<pair<int, int>> memo; // up, down

void goingUp(int start, int num, int& n) {
    for (int i = start+1; i < n; i++) {
        if (vec[start] < vec[i]) {
            if (memo[i].first < (num + 1)) {
                memo[i].first = num + 1;
                goingUp(i, num + 1, n);
            }
        }
    }
}

void goingReverse(int start, int num, int& n) {
    for (int i = start -1 ; i >= 0; i--) {
        if (vec[start] < vec[i]) {
            if (memo[i].second < (num + 1)) {
                memo[i].second = num + 1;
                goingReverse(i, num + 1, n);
            }
        }
    }
}

int main() {
     // μž…λ ₯ λ°›κΈ°
    int n; // μˆ˜μ—΄μ˜ 크기
    cin >> n;
    for (int i = 0; i < n; i++) {
        int tmp;
        cin >> tmp;
        vec.push_back(tmp);
        memo.push_back(make_pair(0, 0));
    }

    // iλ₯Ό ν•˜λ‚˜μ”© λŠ˜λ €κ°€λ©΄μ„œ
    // μ•žμ—μ„œ λ’€λ‘œ
    // μž¬κ·€ν•¨μˆ˜λ‘œ μ¦κ°€ν•˜λ©΄μ„œ 숫자 κΈ°λ‘ν•˜κΈ° (큰 걸둜)
    // λ°˜λŒ€μͺ½λ„ γ„±γ„±

    for (int i = 0; i < n; i++) {
        if (memo[i].first == 0)
            memo[i].first = 1;
        goingUp(i, 1, n);
        if (memo[i].second == 0)
            memo[i].second = 1;
        goingReverse(n-i-1, 1, n);
    }

    int max = 0;
    for (int i = 0; i < n; i++) {
        int res = memo[i].first + memo[i].second;
        if (res > max)
            max = res;
    }

    cout << max - 1;
}
λ°˜μ‘ν˜•