728x90

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

 

1182번: 부분수열의 합

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

www.acmicpc.net

그냥 부분집합 만들고, 그 부분집합이 S인지 확인하면 끝난다.

물론 방법은 쉽지만, 경우가 많이 나오기 때문에 신경쓰지 않으면 시간초과가 날 거 같기도 하다.

 

딱히 생각나는 방법은 없어서 재귀함수로 풀었다.

 

def find(param_list, cur_num):
    if len(param_list) == 0:
        if cur_num == S:
            return 1
        else:
            return 0

    return find(param_list[1:], cur_num + param_list[0]) + find(param_list[1:], cur_num)

 

각 수마다 넣을 지 말지에 대해서 2가지 경우의 수로 나누고, 선택할 수 있는 수가 없을 때의 합을 구해서 S가 맞는 지 확인한다.

지금 작성하면서 보니까 cur_num을 안쓰고 그냥 sum(list)로 했으면 더 깔끔했을 거 같다.

 

이렇게 하면 길이가 5개 일 때, 32가지의 경우가 나오게 된다.

 

하지만 이렇게 구하면 답은 맞지 않을거다.

공집합의 경우의 수도 포함하여 0을 반환하기 때문에 해당 경우는 빼주어야 한다.

import sys

N, S = map(int, sys.stdin.readline().split())

input_list = list(map(int, sys.stdin.readline().split()))


def find(param_list, cur_num):
    if len(param_list) == 0:
        if cur_num == S:
            return 1
        else:
            return 0

    return find(param_list[1:], cur_num + param_list[0]) + find(param_list[1:], cur_num)


result = find(input_list, 0)

if S == 0:
    print(result - 1)
else:
    print(result)

공집합은 0이기 때문에 S가 0일 때만 빼주도록 하자.

'알고리즘 > 브루트포스' 카테고리의 다른 글

백준 1759 암호 만들기  (1) 2024.01.15
백준 14501 퇴사  (0) 2024.01.15
백준 4675 셀프 넘버  (1) 2024.01.15
백준 1065 한수  (0) 2024.01.15
게임판 덮기  (0) 2022.09.17

+ Recent posts