BOJ 1182번 : 부분수열의 합 본문

N개의 정수 원소가 있는 수열에서 부분수열의 합이 S와 같은 경우의 수를 찾는 문제이다.
연속적인 수열이 아니므로, 모든 부분수열을 찾는 과정이 필요하다. 모든 것을 다 해보는 방법을 Brute-Force(완전탐색)이라고 한다.
일단, [1,2,3] 라는 수열이 있을경우, 부분집합은
[1], [2], [3], [1,2], [1,3] [2,3] [1,2,3] 처럼 나올 것 이다.
[1,3]처럼 연속되지 않는 수열을 뽑아내려면 이중반복문 만으로는 충분치 않아보이는데... 흠..... 아래 그림으로 좀더 방법을 찾아보자.

위 그림처럼 진행이 가능하다면, 3개의 원소가 있는 array 에서는 모든 부분수열을 찾을수 있다. 항상 저 나무를 그리면 DFS/BFS 가 먼저 생각나긴 하는데....흠.... 아무튼, 위 그림을 한 배열에서 구현하기 위해서 아래 그림처럼 생각해 보았다.

인덱스가 n 일때, 다음 턴으로 넘어갈 경우, n 까지 구한 부분수열의 합을 제외하고 넘겨주느냐, 포함하고 넘겨주느냐로 위의 트리를 구현할 수 있다.
즉, 재귀 함수를 통해 sum을 넘겨주느냐, sum-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
|
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> arr;
int res = 0;
int n = 0;
int s = 0;
int cnt = 0;
void cur(int ind, int sum) {
if (ind >= n) return;
sum += arr[ind];
if (sum == s)
cnt++;
cur(ind + 1, sum);
cur(ind + 1, sum - arr[ind]);
}
int main() {
int temp;
cin >> n >> s;
for (int i = 0; i < n; i++) {
cin >> temp;
arr.push_back(temp);
}
cur(0, 0);
cout << cnt;
}
|
문제 :
https://www.acmicpc.net/problem/1182
1182번: 부분수열의 합
첫째 줄에 정수의 개수를 나타내는 N과 정수 S가 주어진다. (1 ≤ N ≤ 20, |S| ≤ 1,000,000) 둘째 줄에 N개의 정수가 빈 칸을 사이에 두고 주어진다. 주어지는 정수의 절댓값은 100,000을 넘지 않는다.
www.acmicpc.net
'BOJ' 카테고리의 다른 글
BOJ 10844번 : 쉬운 계단 수 (0) | 2020.03.15 |
---|---|
BOJ 6603번 : 로또 (0) | 2020.03.15 |
BOJ 1463번 : 1로 만들기 (0) | 2020.03.15 |
BOJ 2579 : 계단 오르기 (0) | 2020.03.15 |
BOJ 2163번 : 초콜릿 자르기 (0) | 2020.03.15 |