Post

BOJ 2240 자두나무

BOJ 2240 자두나무

문제

이동횟수가 W로 제한되어있고, 시간 T 동안 떨어지는 자두 최대화하는 경로 탐색

  • $ T \le 1000 , W \le 30 $

복잡도 분석

  • 시간복잡도 O(T*W)
    • 1000 * 30 = 30000, 2초 제한 ok
  • 공간복잡도 O(T*W)
    • 128MB 제한 문제 x

접근법

sequenceDiagram
    participant Prev as DP[t-1] (Previous State)
    participant Decision as Transition Logic
    participant Curr as DP[t] (Current State)

    Note over Decision: if j > 0: max(Stay, Move)
    Note over Decision: else: Stay only
    Prev->>Decision: dp[t-1][j], dp[t-1][j-1]
    Decision->>Curr: max_plums + (pos == tree[t] ? 1 : 0)

dp[t][j] 는 t초에 j번 이동했을 때 얻을 수 있는 최대 자두 개수이다.

  • t-1에 j번 이동했을때 제자리에 있거나 (stay)
  • (j>0 조건에서) t-1에 j-1번 이동했다가 현재 j번째 이동을 수행한 경우
  • 현재 위치는 j%2==0?1:2 ,1번에서 시작

$dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]) + (1 if 현재 위치가 자두 else 0)

풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

const int INF = 1e9;
const ll LINF = 1e18;
const int MOD = 998244353; // or 1e9 + 7

#define rep(i, a, b) for (int i = (a); i < (b); ++i)
#define all(x) (x).begin(), (x).end()

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int T,W; cin>>T>>W;
    vector<int> v(T+1);
    rep(i,1,T+1){
        cin>>v[i];
    }

    vector<vector<int>> dp(T+1,vector<int> (W+1));
    rep(i,1,T+1){
        rep(j,0,W+1){
            int pos = (j%2 == 0) ? 1:2;
            if (j>0){
                dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]) + (pos==v[i]?1:0);
            } else {
                dp[i][j] = dp[i-1][j] + (pos==v[i]?1:0);
            }
        }
    }
    cout << *max_element(dp[T].begin(),dp[T].end());
    return 0;
}

생각해보니 마지막에 max_element(all(dp[T])) 이렇게 할수 있었네… 별로 중요한건 아니고

이동 횟수 홀짝을 이용해서 상태를 줄이고

j=0 은 한번도 움직이지 않고 시작 위치에서 가만히 있는걸 의미함. 이동해서 0번이 되는 건 없다. 그리고 예외처리 안하면 인덱스 오류

나한테는 어려운 문제였다.

This post is licensed under CC BY 4.0 by the author.