백준 28129 - 2022 APC가 어려웠다고요?
위 포스트는 백준 28129 - 2022 APC가 어려웠다고요?의 풀이입니다. dp[i][j] := i번째 수가 j가 되는 경우의 수 dp[i][j]=∑k=max(j−k,a[i−…
2025/03/28
Jinsoolve.
dp[i][0] := 1~i 까지 문제를 푸는데, i를 풀고 나서 남은 코인의 갯수가 0개일 때의 최댓값
dp[i][1] := 1~i 가지 문제를 푸는데, i를 풀고 나서 남은 코인의 갯수와 상관없이 최댓값
위 처럼 2가지 dp를 저장한다고 하자.
먼저 dp[i][0]를 생각해보자.
dp[i-m][0] + (scoreAcc[i] - scoreAcc[i-m]) + bonus[i]dp[i-m][0](scoreAcc[i] - scoreAcc[i-m]) + bonus[i]dp[i-1][1] - score[i]그럼 이번에는 dp[i][1]을 생각해보자.
dp[i][0]에서 이미 1-1번과 2번을 모두 계산했음을 알 수 있다.dp[i-1][1] + score[i]이다.여기서 의문의 생기는데 dp[i-1][1] + score[i]에서 i-1까지의 최댓값 상황에서 코인이 몇 개인지 알아야 i번째에 보너스를 더할지 안 더할지를 할 수 있지 않을까라는 의문이 생길 수 있다.
그러나, 만약 i번째에서 M개를 채웠다면 이는 결국 1-1이다. 그리고 점수들은 모두 음이 아닌 정수이므로 무조건 1-1의 경우가 저장된 dp[i][0]가 클 것이고 결국 max함수로 비교하면 이를 덮어씌울 것이다. 따라서 우리는 dp[i-1][1]이 몇 개의 코인을 모았는지 신경쓸 필요가 없다.
cpp#include <bits/stdc++.h> #define endl "\n" #define all(v) (v).begin(), (v).end() #define For(i, a, b) for(int i=(a); i<(b); i++) #define FOR(i, a, b) for(int i=(a); i<=(b); i++) #define Bor(i, a, b) for(int i=(a)-1; i>=(b); i--) #define BOR(i, a, b) for(int i=(a); i>=(b); i--) #define ft first #define sd second using namespace std; using ll = long long; using lll = __int128_t; using ulll = __uint128_t; using ull = unsigned long long; using ld = long double; using pii = pair<int, int>; using pll = pair<ll, ll>; using ti3 = tuple<int, int, int>; using tl3 = tuple<ll, ll, ll>; template<typename T> using ve = vector<T>; template<typename T> using vve = vector<vector<T>>; template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; } template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; } const int INF = 987654321; const int INF0 = numeric_limits<int>::max(); const ll LNF = 987654321987654321; const ll LNF0 = numeric_limits<ll>::max(); int n, m; ve<ll> score, bonus, scoreAcc; vve<ll> dp; void solve() { cin >> n >> m; score = ve<ll>(n+1,0); bonus = ve<ll>(n+1,0); scoreAcc = ve<ll>(n+1,0); dp = vve<ll>(n+1, ve<ll>(2, -INF0)); FOR(i,1,n) { cin >> score[i]; scoreAcc[i] = score[i] + scoreAcc[i-1]; } FOR(i,1,n) cin >> bonus[i]; dp[0][0] = dp[0][1] = 0; FOR(i,1,n) { ckmax(dp[i][0], dp[i-1][1] - score[i]); if(i-m>=0) ckmax(dp[i][0], scoreAcc[i]-scoreAcc[i-m] + bonus[i] + dp[i-m][0]); ckmax(dp[i][1], dp[i][0]); ckmax(dp[i][1], dp[i-1][1] + score[i]); } cout << dp[n][1] << endl; } int main(void) { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int TC=1; // cin >> TC; FOR(tc, 1, TC) { // cout << "Case #" << tc << ": "; solve(); } return 0; }
위 포스트는 백준 28129 - 2022 APC가 어려웠다고요?의 풀이입니다. dp[i][j] := i번째 수가 j가 되는 경우의 수 dp[i][j]=∑k=max(j−k,a[i−…
2025/03/28
위 포스트는 백준 1055 - 끝이없음의 해설입니다. 문자열이 재귀적으로 반복하는 것을 알 수 있다. 이때 min과 max의 차이가 최대 100개 정도임을 알 수 있고, 우리는…
2025/03/05
위 포스트는 백준 1787 - 문자열의 주기 예측 의 해설입니다. 결국 부분 문자열에서 가장 짧으면서 일치하는 Prefix와 Suffix를 찾으면 된다. (해당 길이를 전체…
2025/03/05
위 포스트는 백준 8872 - 빌라봉 문제의 해설입니다. 위 문제에는 여러 개의 트리가 존재한다. 임의의 2개의 트리를 서로 이을 때 최대 시간이 최소가 되게 하기 위해서는 각…
2025/03/04