본문 바로가기

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

BOJ

BOJ 1182번 : 부분수열의 합

00rigin 2020. 3. 15. 23:18

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(00);
    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
Comments