본문 바로가기
백준브실골/기타

백준 1208, 부분수열의 합 2

by oculis 2023. 4. 5.

내 옆의 개발자, LINT 를 오픈하였습니다.

웹사이트가 필요하면 언제든 연락주세요.

주식 가격을 예측하고 랭크를 올리는 커뮤니티, 오떨 을 오픈하였습니다.

지금 접속하고 예측을 시작해보세요.

728x90

개요

문제 링크
골드 1, Bruteforce, Meet in the middle
40개 원소를 포함하는 수열의 부분수열의 합이 S가 되는 경우의 수


접근

  1. SSP의 Meet in the middle을 쓰는 세 번째 문제, 1182와 이름도 문제도 똑같은데 왜 티어차이가 이렇게 심할까? 브루트포스의 방식의 차이 때문인데, 이 문제는 전형적인 Meet in the middle 문제니까 잘 알아두도록 하자.
  2. SSP를 모른다면 위에 링크된 SSP글을 꼭 읽어보자. 이게 무슨 개념인가 하니, 1182는 N개의 스위치를 가지고 포함/미포함을 선택하는 모든 경우를 따지는 문제였다. 이때 시간복잡도는 O(2^N)인데, 2^40은 대략 1000^4니까 시간에서 터진다.
  3. 이때 선택이 중복을 허용하지 않으므로 배열을 반으로 나누고 반은 왼쪽에서, 나머지는 오른쪽에서 선택하자는 개념이 meet in the middle이다. 구체적인 방법은 선택/미선택의 재귀문 두 개를 선언하는 것이고, 아래 의사코드의 내용은 두 함수를 하나로 합친 것이다. 구체적인 방법론은 SSP에서 읽어보자.

Pseudo code

void dp(int i,int current,int end) {
    if (i==end) {
        if (end==n) ans+=m[sum-current]; // right=sum-left
        else m[current]++; // left
        return;
    }
    dp(i+1,current,end);
    dp(i+1,current+a[i],end);
}

Source code

#include <bits/stdc++.h>
using namespace std;

#define N 41
using ld=long long;
ld n,s,a[N],ans;
map <int,ld> m;

void dp(int i,int k,int e) {
    if (i==e) {
        if (e==n) ans+=m[s-k];
        else m[k]++;
        return;
    }
    dp(i+1,k,e);
    dp(i+1,k+a[i],e);
}

int main() {
    cin>>n>>s;
    for (int i=0;i<n;i++)
        cin>>a[i];
    dp(0,0,n/2);
    dp(n/2,0,n);
    if (!s) ans--;
    cout<<ans;
}
728x90

'백준브실골 > 기타' 카테고리의 다른 글

백준 3284, MASS  (2) 2023.05.04
백준 14921, 용액 합성하기  (0) 2023.05.03
백준 2381, 최대 거리  (0) 2023.04.05
백준 8983, 사냥꾼  (0) 2023.04.05
백준 7453, 합이 0인 네 정수  (0) 2023.04.05
백준 2295, 세 수의 합  (0) 2023.04.05
백준 1182, 부분수열의 합  (0) 2023.04.01
백준 2938, 3으로 나누어 떨어지지 않는 배열  (0) 2023.03.29

댓글