알고리즘/BaekJoon

백준 1182 : 부분수열의 합

꾸준하게 :) 2020. 2. 25. 13:00

문제 링크입니다 https://www.acmicpc.net/problem/1182

 

1182번: 부분수열의 합

첫째 줄에 정수의 개수를 나타내는 N과 정수 S가 주어진다. (1 ≤ N ≤ 20, |S| ≤ 1,000,000) 둘째 줄에 N개의 정수가 빈 칸을 사이에 두고 주어진다. 주어지는 정수의 절댓값은 100,000을 넘지 않는다.

www.acmicpc.net

재귀 함수를 이용해 모든 경우를 탐색하는 방식으로 문제를 해결했습니다. 합이 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<cstdio>
 
int n, s, num[20], ret;
 
// 부분집합의 모든 경우를 보기 위해 고를지 말지 결정하는 i와
// 현재까지 고른 원소들의 합을 나타내는 sum을 인자로 받아
// 정답인 경우를 찾으면 ret를 증가시키는 함수
void solve(int i, int sum) {
 
    // 모든 원소에 대해서 고르거나 고르지 않았으면
    if (i == n){
        // 고른 원소들의 합이 s이면
        if (sum == s) {
            ret++;    // 정답인 경우이므로 ret 증가
        }
 
        // 고른 원소들의 합이 s이든 아니든 return
        return;
    }
    solve(i + 1, sum + num[i]); // 현재 원소를 고르고 다음으로 갑니다
    solve(i + 1, sum);          // 현재 원소를 고르지 않고 다음으로 갑니다
}
 
int main(void) {
 
    scanf("%d%d"&n, &s);
    for (int i = 0; i < n; i++)
        scanf("%d"&num[i]);
 
    solve(00);
 
    // s가 0일 때는 아무것도 고르지 않은 경우가 답에 포함되어 있습니다
    // 하지만 문제에서 "크기가 양수인 부분집합 중에서"라 했기 때문에 -1을 해줍니다
    if (s == 0) ret -= 1;
 
    printf("%d", ret);
    return 0;
}
cs