BOJ

백준 2156 - 포도주 시식

yanJuicy 2019. 7. 12. 23:11
반응형

문제

https://www.acmicpc.net/problem/2156

 

2156번: 포도주 시식

효주는 포도주 시식회에 갔다. 그 곳에 갔더니, 테이블 위에 다양한 포도주가 들어있는 포도주 잔이 일렬로 놓여 있었다. 효주는 포도주 시식을 하려고 하는데, 여기에는 다음과 같은 두 가지 규칙이 있다. 포도주 잔을 선택하면 그 잔에 들어있는 포도주는 모두 마셔야 하고, 마신 후에는 원래 위치에 다시 놓아야 한다. 연속으로 놓여 있는 3잔을 모두 마실 수는 없다. 효주는 될 수 있는 대로 많은 양의 포도주를 맛보기 위해서 어떤 포도주 잔을 선택해야 할지 고

www.acmicpc.net

 

풀이

세 가지 포도주를 연속적으로 선택할 수 없으므로 n 번째에서 선택을 세 가지 경우로 나눈다. 

0이면 포도주를 선택 하지 않는 경우,

1이면 포도주를 1번 연속 선택한 (n) 경우,

2이면 포도주를 2번 연속 선택한 (n - 1, n) 경우로 나눈다.

n 번째에서 세 가지 경우 중 가장 큰 값으로 선택을 하면 된다.

 

arr[n] = n번째 포도주 양, dp[n][state] = n번째 포도주잔과 state(0, 1, 2) 라고 하면 다음의 점화식을 구할 수 있다.

dp[n][0] = max{

  dp[n-1][0],

  dp[n-1][1],

  dp[n-1[2]

}

dp[n][1] = dp[n - 1][0] + arr[n]

dp[n][2] = dp[n - 1][1] + arr[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
#include <iostream>
#include <algorithm>
 
using namespace std;
 
int n;
int arr[10001];
int dp[10001][3];
int result;
 
// 2: 2번 연속 선택,  1: 1번 연속 선택, 0: 선택 X
int f(int n, int state)
{
    if (n <= 0return 0;
    if (dp[n][state]) return dp[n][state];
 
    if (state == 0return dp[n][state] = max(f(n - 10), max(f(n - 11), f(n - 12)));
    else if (state == 1return dp[n][state] = f(n - 10+ arr[n];
    else return dp[n][state] = f(n - 11+ arr[n];
}
 
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
 
    cin >> n;
 
    for (int i = 1; i <= n; i++cin >> arr[i];
 
    result = max(f(n, 0), max(f(n, 1), f(n, 2))); 
 
    cout << result;
 
    return 0;
}
 
cs

 

바텀업 방식

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
#include <iostream>
#include <algorithm>
 
using namespace std;
 
int n;
int arr[10001];
int dp[10001][3];
int result;
 
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
 
    cin >> n;
 
    for (int i = 1; i <= n; i++cin >> arr[i];
 
    dp[1][0= 0; dp[1][1= arr[1]; dp[1][2= 0;
    for (int i = 2; i <= n; i++)
    {
        dp[i][0= max(dp[i - 1][0], max(dp[i - 1][1], dp[i - 1][2]));
        dp[i][1= dp[i - 1][0+ arr[i];
        dp[i][2= dp[i - 1][1+ arr[i];
    }
 
    result = max(dp[n][0], max(dp[n][1], dp[n][2]));
    cout << result;
 
    return 0;
}
 
cs

 

반응형