Jinsoolve.

Categories

Tags

1월 안에는 꼭...

Portfolio

About

백준 1462 - 퀴즈쇼

Created At: 2024/12/26

2 min read

BOJ 1462 - 퀴즈쇼

풀이

dp[i][0] := 1~i 까지 문제를 푸는데, i를 풀고 나서 남은 코인의 갯수가 0개일 때의 최댓값
dp[i][1] := 1~i 가지 문제를 푸는데, i를 풀고 나서 남은 코인의 갯수와 상관없이 최댓값

위 처럼 2가지 dp를 저장한다고 하자.

먼저 dp[i][0]를 생각해보자.

  1. i번 문제를 맞춰서 보너스 코인을 받아 코인을 모두 소모함.
    dp[i-m][0] + (scoreAcc[i] - scoreAcc[i-m]) + bonus[i]
  2. i-m까지 문제를 풀고 나서 코인이 0개가 되었을 때의 최댓값 := dp[i-m][0]
  3. i-m+1 ~ i 까지의 문제를 모두 맞추고 i번 째 문제에서 보너스 점수를 받음 := (scoreAcc[i] - scoreAcc[i-m]) + bonus[i]
  4. i번 문제를 틀려서 모든 코인을 잃음.
    dp[i-1][1] - score[i]
    i-1까지 최댓값에 i번째 문제를 틀려서 점수를 빼준다.
    위와 같이 2가지 케이스가 된다.

그럼 이번에는 dp[i][1]을 생각해보자.

  1. i번 맞추기
  2. i번을 맞춤으로써, M개 채움
  3. i번을 맞춰도 M개를 채우지 못 함.
  4. i번 틀리기
    위와 같이 총 3개의 케이스가 있다.
    그러나 우리는 dp[i][0]에서 이미 1-1번과 2번을 모두 계산했음을 알 수 있다.
    그렇다면 우리는 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]이 몇 개의 코인을 모았는지 신경쓸 필요가 없다.

코드

1#include <bits/stdc++.h> 2 3#define endl "\n" 4#define all(v) (v).begin(), (v).end() 5#define For(i, a, b) for(int i=(a); i<(b); i++) 6#define FOR(i, a, b) for(int i=(a); i<=(b); i++) 7#define Bor(i, a, b) for(int i=(a)-1; i>=(b); i--) 8#define BOR(i, a, b) for(int i=(a); i>=(b); i--) 9#define ft first 10#define sd second 11 12using namespace std; 13using ll = long long; 14using lll = __int128_t; 15using ulll = __uint128_t; 16using ull = unsigned long long; 17using ld = long double; 18using pii = pair<int, int>; 19using pll = pair<ll, ll>; 20using ti3 = tuple<int, int, int>; 21using tl3 = tuple<ll, ll, ll>; 22 23template<typename T> using ve = vector<T>; 24template<typename T> using vve = vector<vector<T>>; 25 26template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; } 27template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; } 28 29const int INF = 987654321; 30const int INF0 = numeric_limits<int>::max(); 31const ll LNF = 987654321987654321; 32const ll LNF0 = numeric_limits<ll>::max(); 33 34int n, m; 35ve<ll> score, bonus, scoreAcc; 36vve<ll> dp; 37 38void solve() { 39 cin >> n >> m; 40 score = ve<ll>(n+1,0); 41 bonus = ve<ll>(n+1,0); 42 scoreAcc = ve<ll>(n+1,0); 43 dp = vve<ll>(n+1, ve<ll>(2, -INF0)); 44 45 FOR(i,1,n) { 46 cin >> score[i]; 47 scoreAcc[i] = score[i] + scoreAcc[i-1]; 48 } 49 FOR(i,1,n) cin >> bonus[i]; 50 51 dp[0][0] = dp[0][1] = 0; 52 FOR(i,1,n) { 53 ckmax(dp[i][0], dp[i-1][1] - score[i]); 54 if(i-m>=0) ckmax(dp[i][0], scoreAcc[i]-scoreAcc[i-m] + bonus[i] + dp[i-m][0]); 55 56 ckmax(dp[i][1], dp[i][0]); 57 ckmax(dp[i][1], dp[i-1][1] + score[i]); 58 } 59 cout << dp[n][1] << endl; 60} 61 62int main(void) { 63 ios_base::sync_with_stdio(false); 64 cin.tie(nullptr); 65 cout.tie(nullptr); 66 67 int TC=1; 68// cin >> TC; 69 FOR(tc, 1, TC) { 70// cout << "Case #" << tc << ": "; 71 solve(); 72 } 73 74 75 return 0; 76}

관련 포스트가 4개 있어요.

백준 10321 - 요새 건설

2025/01/13

NEW POST
profile

김진수

Currently Managed

Currently not managed

© 2025. junghyeonsu & jinsoolve all rights reserved.