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

 

1126번: 같은 탑

첫째 줄에 조각의 개수 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄에 각 조각의 높이가 주어진다. 높이는 500,000보다 작거나 같은 자연수이고, 모든 조각의 높이의 합은 500,000을 넘

www.acmicpc.net

풀이

$dp[i][diff]:$ $i$ 까지 고려해서 쌓은 경우에서 차이가 $diff$ 일 때 더 높은쪽의 높이의 최댓값

dp[i][diff]

※ $i, diff$ 이 불가능한 경우: $dp[i][diff] = -1$

 

$dp[i - 1][j] \neq -1$ 일 때

  1. $i$ 블록 안 쌓는 경우
    • $dp[i][j] = max(dp[i][j], dp[i - 1][j])$
  2. $i$ 블록 쌓는 경우
    1. 높은 쪽에 쌓는 경우
      • $dp[i][j + a[i]] = max(dp[i][j + a[i]], dp[i - 1][j] + a[i])$
    2. 낮은 쪽에 쌓는 경우
      1. $a[i] < j$
        • $dp[i][j - a[i]] = max(dp[i][j - a[i]], dp[i - 1][j])$
      2. $a[i] \geq j$
        • $dp[i][a[i] - j] = max(dp[i][a[i] - j], dp[i - 1][j] + a[i] - j)$

코드

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int N;
    cin >> N;

    vector<int> a(N);
    vector<vector<int> > dp(N, vector<int> (500001, -1));
    for (int i = 0; i < N; ++i) {
        cin >> a[i];
    }
    
    dp[0][0] = 0;
    dp[0][a[0]] = a[0];
    for (int i = 1; i < N; ++i) {
        for (int j = 0; j <= 500000; ++j) {
            if (dp[i - 1][j] == -1) continue;
            dp[i][j] = max(dp[i][j], dp[i - 1][j]);
            if (j + a[i] <= 500000) dp[i][j + a[i]] = max(dp[i][j + a[i]], dp[i - 1][j] + a[i]);
            if (a[i] < j) {
                dp[i][j - a[i]] = max(dp[i][j - a[i]], dp[i - 1][j]);
            } else {
                dp[i][a[i] - j] = max(dp[i][a[i] - j], dp[i - 1][j] + a[i] - j);
            }
        }
    }
    if (dp[N - 1][0] > 0) {
        cout << dp[N - 1][0] << '\n';
    } else {
        cout << "-1\n";
    }
}
728x90

'PS > BOJ' 카테고리의 다른 글

백준 2316번: 도시 왕복하기 2  (0) 2022.02.20
백준 13537번: 수열과 쿼리 1  (0) 2022.02.19
백준 11377번: 열혈강호 3  (0) 2022.02.18
백준 19585번: 전설  (0) 2022.02.15
백준 4225번: 쓰레기 슈트  (0) 2022.02.12

+ Recent posts