https://www.acmicpc.net/problem/1126
1126번: 같은 탑
첫째 줄에 조각의 개수 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄에 각 조각의 높이가 주어진다. 높이는 500,000보다 작거나 같은 자연수이고, 모든 조각의 높이의 합은 500,000을 넘
www.acmicpc.net
풀이
$dp[i][diff]:$ $i$ 까지 고려해서 쌓은 경우에서 차이가 $diff$ 일 때 더 높은쪽의 높이의 최댓값
※ $i, diff$ 이 불가능한 경우: $dp[i][diff] = -1$
$dp[i - 1][j] \neq -1$ 일 때
- $i$ 블록 안 쌓는 경우
- $dp[i][j] = max(dp[i][j], dp[i - 1][j])$
- $i$ 블록 쌓는 경우
- 높은 쪽에 쌓는 경우
- $dp[i][j + a[i]] = max(dp[i][j + a[i]], dp[i - 1][j] + a[i])$
- 낮은 쪽에 쌓는 경우
- $a[i] < j$
- $dp[i][j - a[i]] = max(dp[i][j - a[i]], dp[i - 1][j])$
- $a[i] \geq j$
- $dp[i][a[i] - j] = max(dp[i][a[i] - j], dp[i - 1][j] + a[i] - 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 |