알고리즘(Algorithm)의 종류, 분류/여러 가지 기법
[JAVA]백준 1182번: 부분수열의 합
Miiko
2021. 9. 30. 00:22
https://www.acmicpc.net/problem/1182
1182번: 부분수열의 합
첫째 줄에 정수의 개수를 나타내는 N과 정수 S가 주어진다. (1 ≤ N ≤ 20, |S| ≤ 1,000,000) 둘째 줄에 N개의 정수가 빈 칸을 사이에 두고 주어진다. 주어지는 정수의 절댓값은 100,000을 넘지 않는다.
www.acmicpc.net
비트마스킹에 대한 글을 포스팅 한 후 금방 터득한 생생한 지식으로 바로 풀어보았다✨
| 문제 해결방법
부분집합 구하는 공식 + 비트마스킹
부분집합을 구할 때
1. boolean배열을 사용할 수도 있고
2. 비트마스킹 기법을 사용할 수도 있다.
이번 문제에서는 비트마스킹 기법을 사용하였고,
이 기법은 비트단위로 정보를 처리하기 때문에 메모리를 적게 사용할 뿐만 아니라 수행 속도가 빠르다는 장점이 있다.
[JAVA] 해설 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class BOJ_1182 {
static int N, S, ans;
static int[] arr;
static int flag = 0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
S = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
ans = 0;
method(0, 0);
System.out.println(ans);
}
// 부분집합 생성 메서드
private static void method(int flag, int cnt) {
if (cnt == N) {
// 공집합인 경우
if (flag == 0)
return;
int sum = 0;
for (int i = 0; i < N; i++) {
// i번째 비트가 1이라면 arr[i]값을 sum에 더하기
if (((1 << i) & flag) > 0) {
sum += arr[i];
}
}
// 합이 S가 된다면 개수 추가
if (sum == S)
ans++;
return;
}
// cnt번째 비트를 선택하지 않는 경우
method(flag, cnt + 1);
// cnt번째 비트를 선택한 경우
flag = (1 << cnt) | flag;
method(flag, cnt + 1);
}
}
[제출] 메모리 및 시간