새소식

💻 Computer/🐘 Algorithm

[14002] 가장 긴 증가하는 부분 수열 4 - c++

  • -

https://www.acmicpc.net/problem/14002

 

14002번: 가장 긴 증가하는 부분 수열 4

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이

www.acmicpc.net

일단 예전에 풀었던 가장 긴 증가하는 부분 수열을 구하는 알고리즘을 사용하는 것이라는 건 자명한 사실! 

하지만 여기선 추가 된것이 있었으니, 그 경로까지 구해야 하는 것이다.

이슈다 응용은 못한다....

일단 당연히 문제에 대해 고민을 해보고 답을 봤다.


풀이 아이디어

가장 긴 배열을 구하며 경로도 추가 적으로 pre 라는 배열에 저장한다.

사실 예전 이런 비슷한 문제를 풀었던 적이 있어 따로 배열에 저장해야겠다고 생각했으나 어떻게 이 문제에 적용시켜야 할지 몰랐다.

결국 난 몰랐던 거다.

 

가장 위의 인덱스 부터 내려오면서 연결리스트 구현 했던 방식으로 풀어내는 것을 보고 감탄했다...

 

말로만 하면 어려우니 코드를 보며 분석해보자


CODE

// 포도주 시식
#include <bits/stdc++.h>

using namespace std;
void init(){
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
}

int n;
int a[1001], d[1001], pre[1001];

int main(){
  init();
  cin >> n;
  for(int i = 1; i <= n; ++i) cin >> a[i];

  for(int i = 1; i <= n; ++i){
    for(int j = 1; j < i; ++j){
      if(a[i] > a[j] && d[i] < d[j]+1){
        d[i] = d[j] + 1;
        pre[i] = j;
      }
    }
  }

  int maxi = 1, maxd = d[1];
  for(int i = 1; i <= n; ++i){
    if(maxd < d[i]){
      maxi = i;
      maxd = d[i];
    }
  }

  deque <int> ans;
  int cur = maxi;
  while(cur){
    ans.push_front(a[cur]);
    cur = pre[cur];
  }
  cout << ans.size() << '\n';
  for(auto x : ans) cout << x << ' ';  
  return 0;
}

 

1. 가장 긴 것을 찾으며 경로를 저장하는 로직

for(int i = 1; i <= n; ++i){
    for(int j = 1; j < i; ++j){
      if(a[i] > a[j] && d[i] < d[j]+1){
        d[i] = d[j] + 1;
        pre[i] = j;
      }
    }
  }

 

최대 값의 경로가 바로바로 저장된다.

input => 10 20 10 30 20 50
dp => 0 1 0 2 1 3 
pre => 0 1 0 2 1 4

위와 같은 식으로 저장된다.

 

2. 가장 긴 부분의 인덱스를 찾는다.

int maxi = 1, maxd = d[1];
  for(int i = 1; i <= n; ++i){
    if(maxd < d[i]){
      maxi = i;
      maxd = d[i];
    }
  }

maxi에 가장 긴 부분의 마지막 인덱스가 들어가게 된다

 

3. 경로를 따라가며 덱에 저장한다

deque <int> ans;
  int cur = maxi;
  while(cur){
    ans.push_front(a[cur]);
    cur = pre[cur];
  }

연결리스트 구현 할 때 했던 것과 똑같은 방식이다. pre배열의 저장된 값을 따라가다가 마지막 0이 나오면 멈추게 된다.


문제를 풀며

DP문제 정말 너무 어렵다. 실버 등급도 어려운데 골드 문제를 푸는 게 맞나 싶지만 할 수 있다고 생각하고 그렇게 믿고 싶었다. 하지만 답을 봐버렸다...

과연 이렇게 계속 풀어 나가는 것이 맞는지는 모르겠으나 정말 조금씩 감이 잡히기 시작하는 것 같다. 진짜 조금...

그렇다고 아직까지 나 스스로 답을 맞혀 보진 못했다 ㅎㅎ 

더 풀자..ㅜ 계속 풀자 ㅜ

'💻 Computer > 🐘 Algorithm' 카테고리의 다른 글

[2302] 극장좌석 - c++  (0) 2023.06.17
[12865] 평범한 배낭 - c++  (2) 2023.06.14
[2240]자두 나무 - c++  (2) 2023.06.10
[17144]미세먼지 안녕! - c++  (2) 2023.06.09
[11055]가장 큰 증가하는 부분 수열- C++  (0) 2023.06.06
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.