문제 주소 : www.acmicpc.net/problem/1208
문제 확인
완전 탐색을 하게 되면 시간 초과가 나므로 이를 방지하기 위해 해쉬와 분할을 사용합니다.
dfs의 변형으로 알고리즘만 이해한다면 쉽게 풀 수 있습니다.
풀이
n은 최대 40, 각 수는 절댓값이 100000을 넘지 않으므로 해쉬의 컨테이너를 4000000개로 설정하고 2000000을 기준으로 음수와 양수를 구분합니다.
백준 알고리즘 분류에 "중간에서 만나기" 가 의미하는 것을 생각해 보면 dfs를 반으로 나누어 중간에서 부분 수열을 합친다고 생각하면 됩니다.
1 ~ n/2 까지의 수열에서 부분 수열을 먼저 계산하고 n/2 + 1 ~ n 까지의 수열에서 부분 수열 계산 시 s값과 맞아떨어지는 수를 찾으면 개수만큼 결과에 더해줍니다.
result += hash[s - val + 2000000]
( = 현재 값이 7이며 s가 10일 시 left에서 구한 3의 개수가 결과에 더해줘야 하므로 hash[10 - 7 + 2000000] => hash[2000003])
코드
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 <cstdio>
#define MID 2000000
using namespace std;
int n, s, m, ary[40], hs[4000001];
long long res;
void left(int cur, int val) {
if (cur != m) {
left(cur + 1, val);
left(cur + 1, val + ary[cur]);
}
else
hs[val + MID]++;
}
void right(int cur, int val) {
if (cur != n) {
right(cur + 1, val);
right(cur + 1, val + ary[cur]);
}
else if (-2000000 <= s - val && s - val <= 2000000)
res += hs[s - val + MID];
}
int main() {
scanf("%d%d", &n, &s);
m = n >> 1;
for (int i = 0; i < n; i++)
scanf("%d", &ary[i]);
left(0, 0);
right(m, 0);
printf("%lld", s ? res : res - 1);
}
|
cs |
반응형
'알고리즘 문제 > [백준]' 카테고리의 다른 글
[백준] 2042 구간 합 구하기 (0) | 2021.01.01 |
---|---|
[백준] 1867 돌멩이 제거 (0) | 2020.12.31 |
[백준] 2315 가로등 끄기 (0) | 2020.12.29 |
[백준] 1150 백업 (0) | 2020.12.19 |
[백준] 8895 막대 배치 (0) | 2020.12.18 |