-

[DP] 백준 5557번 - 1학년 본문

5. DP

[DP] 백준 5557번 - 1학년

asdklfjlasdlfkj 2020. 1. 27. 18:57

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

 

5557번: 1학년

문제 상근이가 1학년 때, 덧셈, 뺄셈을 매우 좋아했다. 상근이는 숫자가 줄 지어있는 것을 보기만 하면, 마지막 두 숫자 사이에 '='을 넣고, 나머지 숫자 사이에는 '+' 또는 '-'를 넣어 등식을 만들며 놀고 있다. 예를 들어, "8 3 2 4 8 7 2 4 0 8 8"에서 등식 "8+3-2-4+8-7-2-4-0+8=8"을 만들 수 있다. 상근이는 올바른 등식을 만들려고 한다. 상근이는 아직 학교에서 음수를 배우지 않았고, 20을 넘는 수는 모른다.

www.acmicpc.net

전형적인 DP 문제였습니다.

배열의 성격을 잘 결정하고, 초기값을 잘 결정해준 뒤 점화식을 세워 코딩하면 되는 문제입니다.

 

dp[i][j]를 설정하였는데 이는

'i번째 까지 숫자를 활용해 만든 수가 j가 되는 경우의 수'를 저장하는 배열입니다.

 

초기값은 

dp[0][number[0]] = 1로 설정해 줄 수 있습니다.

즉, 0번째 까지 숫자를 활용해 만든 수가 number[0]인 경우의 수로, 이는 곧 한 가지 경우밖에 없습니다.

 

다음으로 점화식은

이전숫자까지 활용해 j를 만든 경우의 수가 존재한다했을 때, 현재의 수 number[i]를 더한 결과가 20이하인 경우와 뺀 결과가 0 이상인 경우를 생각해주면 됩니다.

즉, for(int i=0; i<N-1; i++)

      for(int j=0; j<21; j++) 루프를 돌 때

dp[i-1][j]가 존재한다면, 그리고

  1. j + number[i] <= 20이라면 dp[i][j+number[i]] += dp[i-1][j]; 를 해줄 수 있으며,

  2. j - number[i] >= 0이라면 dp[i][j-number[i]] += dp[i-1][j];를 해줄 수 있습니다.

 

최종적으로 N-2까지 활용한 결과가 number[N-1]이 되는 경우의 수를 구하는 것이므로 

dp[N-2][number[N-1]]을 출력하면 됩니다. 이 때, dp배열의 자료형은 long long으로 설정했습니다.

 

아래는 코드입니다.

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 <stdio.h>
#pragma warning(disable:4996)
int numbers[100];
long long dp[100][21];
int main(){
    int N;
    for (int i = 0; i < 100; i++){
        numbers[i] = 0;
        for (int j = 0; j < 21; j++){
            dp[i][j] = 0;
        }
    }
    scanf("%d"&N);
    for (int i = 0; i < N; i++){
        scanf("%d"&numbers[i]);
    }
    dp[0][numbers[0]] = 1;
    // dp[x][y] : x번째 까지 요소를 갖고 y를 만드는 경우의 수.
 
    for (int i = 1; i <= N - 2; i++){
        for (int j = 0; j <= 20; j++){
            if (dp[i - 1][j]){
                if (j + numbers[i] <= 20) dp[i][j + numbers[i]] += dp[i - 1][j]; 
                // 이전에 만든 숫자 j에다가 현재 숫자 numbers[i]를 더해 20이하면 
                // 현재 i번째 까지 요소를 갖고 j+numbers[i]를 만드는 경우의 수는
                // 이전까지 j를 만든 경우의 수를 더해주는 것과 같다.
                if (j - numbers[i] >= 0) dp[i][j - numbers[i]] += dp[i - 1][j];
            }
        }
    }
    printf("%lld", dp[N - 2][numbers[N - 1]]);
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

'5. DP' 카테고리의 다른 글

[DP] BOJ - 10844번 (쉬운계단수)  (0) 2020.01.29
[DP] 백준 4811번 - 알약  (0) 2020.01.28
[DP] 백준 2193번 - 이친수  (0) 2020.01.08
[DP] 백준 9095번 - 1, 2, 3 더하기  (0) 2020.01.08
[DP] 백준 1149번 - RGB 거리  (0) 2020.01.08
Comments