백준의 퇴사2(15486) 문제이다.

[ 문제 바로가기 ]


[ 문제풀이 ]

1) 퇴사1과 동일한 조건에 똑같은 문제이지만 N의 범위가 150만으로 퇴사1에서 사용했던 방법인 완전탐색으로는

   절대 시간내에 통과할 수 없다.

   따라서 본인은 이 문제에서는 Dynamic Programming 방식을 사용해서 접근해보았다.

   DP과정을 위해서 DP[] 라는 배열을 하나 선언해 주었다.

   DP배열에 저장되는 값은 "현재 시점까지 벌 수 있는 최대 액수"를 의미한다.

   조금 더 구체적으로 말해보자면 DP[a] = b 이다 의 의미는 "a일 까지의 최대 액수는 b원입니다"가 된다.

   여기서 주의해줘야 할 것은 DP[a] 에서 a가 의미하는 것은 그 날 까지가 아닌, 그 전날까지를 의미한다.

   즉, DP[4] = 10 이라고 했을 때, 4일까지 일을 했을 때 벌 수 있는 돈을 의미하는 것이 아니라, 4일전까지, 즉

   1 ~ 3 일동안 벌 수 있는 최대 액수를 의미한다. 더욱더 쉽게 생각하면, 일을 한 후에 돈을 받는다고 생각하면 된다.

  

2) 구체적인 풀이에 들어가보자.

   이해하기 쉽게 문제에 주어진 예제입력 1을 예제로 삼아서 풀어 나가보자.

  

   예제입력1의 일정표이다.

   먼저 DP[1]의 값을 생각해보자. DP[1]이라는 것은 "1일전까지 일을 해서 벌 수 있는 최대 액수"를 의미한다.

   당연히 0원일 것이다. 그럼 1일날 일을 하게 된다면, 언제 돈을 받게될까? 위에서 말한것 처럼 일을 한 후에

   돈을 받는 개념으로 접근해보면, 4일날 받을 수 있음을 알 수 있다.

   그럼 우리는 1일을 계산하면서 DP[4]의 값을 갱신할 수 있다. DP[4] = 10으로 갱신될 것이다.

   다시한번 정리해보자면, "1일날 일을 함으로써 돈은 3일후인 4일날 받을 수 있다. 따라서 4일까지 벌 수 있는

   최대액수는 10원이다" 라는 것을 알 수 있게 되는 것이다.

   2일로 가보자. 현재 2일까지 일을 해서 벌 수 있는 최대 금액은 0원이다.

   2일날 일을 하면 돈을 7일날 받게 될 것이다. 즉, DP[7] = 20 이라고 우리는 갱신할 수 있다.

   3일로 가보자. 현재 3일까지 일을 해서 벌 수 있는 최대 금액은 0원이다.

   3일날 일을 하면 4일날 받게 될 것이다. 그럼 4일까지 벌 수 있는 최대 액수는 얼마일까 ??

   지금 현재 '1일'에 의해서 4일까지 벌 수 있는 액수가 10원이라는 것을 알고 있다. 하지만, '3일'날 일을

   한다고해서 10원보다 더 큰 액수를 벌 수 있는 것은 아니므로 그대로 DP[4] = 10으로 유지될 것이다.

   4일로 가보자. 현재 4일까지 일을 해서 벌 수 있는 최대 금액은 10원이다.

   4일날 일을 하게 되면 5일날 받게 될 것이다. 그럼 5일까지 벌 수 있는 최대 액수는 얼마일까 ??

   5일날 벌 수 있는 최대액수는 둘 중 하나일 것이다.

   1. 4일까지 일을 해서 벌 수 있는 최대 액수 + 4일날 일을 함으로써 벌 수 있는 돈

   2. 기존에 설정된 5일까지 일을 해서 벌 수 있는 최대액수

   두개 중에 하나일 것이다. 1번 같은 경우, 4일까지 일을해서 벌 수 있는 최대액수 = 10 + 4일날 일을 함으로써 벌 수 있는

   돈 = 20 이 되어서 30원이 될 것이고, 2번 같은 경우 아직 5일은 벌 수 있는 돈이 없으므로 0원일 것이다.

   즉, DP[5] = 30으로 갱신될 것이다.

   위와 같은 방식으로 탐색을 해주면 된다. 단, 일을 함으로써 받게 되는 돈의 날짜가 N + 1 보다 커져버리면

   그 일은 할 수 없다.

   왜냐하면, N + 1일까지의 값을 계산을 하면 N일까지 일을 했을 때의 최댓값을 구할 수 있지만, 그 이상은 퇴사를

   하기 때문에 돈을 못받기 때문이다.


[ 소스코드 ]

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include<iostream>
 
#define endl "\n"
#define MAX 1500010
using namespace std;
 
int N, Answer;
int DP[MAX];
int Arr[MAX][2];
 
int Bigger(int A, int B) { if (A > B) return A; return B; }
 
void Input()
{
    cin >> N;
    for (int i = 1; i <= N; i++)
    {
        cin >> Arr[i][0>> Arr[i][1];
    }
    // Arr[i][0] = 걸리는 날짜
    // Arr[i][1] = 돈
}
 
void Solution()
{
    int Current_Max = 0;
    for (int i = 1; i <= N + 1; i++)
    {
        Current_Max = Bigger(Current_Max, DP[i]);
        if (i + Arr[i][0> N + 1continue;
        
        DP[i + Arr[i][0]] = Bigger(Current_Max + Arr[i][1], DP[i + Arr[i][0]]);
    }
    Answer = Current_Max;
}
 
void Solve()
{
    Input();
    Solution();
    cout << Answer << endl;
}
 
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    freopen("Input.txt""r", stdin);
    Solve();
 
    return 0;
}
cs

 











'[ BOJ Code ] > # BOJ -' 카테고리의 다른 글

[ 백준 1103 ] 게임 (C++)  (0) 2020.02.20
[ 백준 1026 ] 보물 (C++)  (2) 2020.02.19
[ 백준 15653 ] 구슬 탈출4 (C++)  (0) 2020.02.06
[ 백준 15644 ] 구슬 탈출3 (C++)  (4) 2020.02.04
[ 백준 18160 ] 숫자 야구 (C++)  (0) 2020.01.31

+ Recent posts