AOJ - JLIS

사실 이 문제는 종만북에서 난이도가 하지만 꽤 어렵다.

일단 반복문 DP로 풀기는 구현이 잘 안나와서 재귀로 틀었다.

$dp_{i,\,j}$ = 현재 $a$의 인덱스가 $i$ 이고 $b$의 인덱스가 $j$ 일 때 끝까지 JLIS 를 구성했을 때 최대 길이라고 하자.

이제 $a_i$나 $b_j$ 보다 큰 값으로 나아갈 수밖에 없다. 왜냐면 $a_i$와 $b_j$ 는 이미 수열에 포함되었기 때문에 그 다음에 나오는 수는 이 두개보다 커야 하기 때문이다.

따라서 $i+1$ 보다 큰값이나 $j+1$ 보다 큰 값중에 $a_i$ 와 $b_j$ 보다 큰 값을 가진 수로 점프해줘서 dp를 구해주면 된다.

void solve() {  
   int n, m = 0;  
   cin >> n >> m;  
   vi a(n), b(m);  
   fv(a);  
   fv(b);  
  
   a.insert(a.begin(), -1e15);  
   b.insert(b.begin(), -1e15);  
  
   vvi dp(n + 1, vi(m + 1, -1));  
  
   function<int(int, int)> fn = [&](int l, int r) -> int {  
      int &ret = dp[l][r];  
      if (~ret) return ret;  
      ret = 0;  
  
      int mx = max(a[l], b[r]);  
  
      for (int i = l + 1; i <= n; i++) {  
         if (a[i] > mx) {  
            ret = max(ret, 1 + fn(i, r));  
         }  
      }  
      for (int i = r + 1; i <= m; i++) {  
         if (b[i] > mx) {  
            ret = max(ret, 1 + fn(l, i));  
         }  
      }  
  
      return ret;  
   };  
  
   cout << fn(0, 0) << endl;  
}

Comments