알고리즘/백준
백준-14225번/부분수열의 합(java)
연향동큰손
2024. 8. 2. 18:58
문제 이해
문제
수열 S가 주어졌을 때, 수열 S의 부분 수열의 합으로 나올 수 없는 가장 작은 자연수를 구하는 프로그램을 작성하시오.
예를 들어, S = [5, 1, 2]인 경우에 1, 2, 3(=1+2), 5, 6(=1+5), 7(=2+5), 8(=1+2+5)을 만들 수 있다. 하지만, 4는 만들 수 없기 때문에 정답은 4이다.
입력
첫째 줄에 수열 S의 크기 N이 주어진다. (1 ≤ N ≤ 20)
둘째 줄에는 수열 S가 주어진다. S를 이루고있는 수는 100,000보다 작거나 같은 자연수이다.
출력
첫째 줄에 수열 S의 부분 수열의 합으로 나올 수 없는 가장 작은 자연수를 출력한다.
주의할 점 : 수열 S를 이루고 있는 숫자가 100,000보다 작거나 같은 자연수, 수열의 크기는 최대 20 ==> 수열의 합으로 만들 수 있는 자연수를 기록하는 boolean 배열 sum의 크기 == 20 * 100,000 = 2000000
이것을 고려하지 않고 풀었다가 전체적인 로직은 맞게 구현 했으나 반례때문에 계속 틀렸다..

문제 풀이
모든 경우의 수를 구하면서 문제를 풀어야 하기 때문에 dfs를 구현해서 합으로 만들 수 있는 숫자를 기록했다.
static void dfs(int start, int value){
if(start>=N){
return;
}
for(int i=start; i<N; i++){
if(!visit[i]) {
visit[i]=true;
value=value+arr[i];
if(value<=2000000) {
sum[value] = true;
}
dfs(i+1,value);
value-=arr[i];
visit[i]=false;
}
}
}
여기서 visit[i]를 다시 false로 바꾸고 value에서 다시 arr[i]를 빼줘야지 수열의 숫자를 더하지 않은 경우도 구할 수 있다.
<전체 코드>
import java.util.Arrays;
import java.util.Scanner;
public class Problem14225 {
static int[] arr;
static int N;
static boolean[] visit;
static boolean[] sum=new boolean[2000001];
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
N=scanner.nextInt();
arr=new int[N];
visit=new boolean[N];
for(int i=0; i<N; i++){
arr[i]=scanner.nextInt();
}
Arrays.fill(visit,false);
Arrays.fill(sum,false);
dfs(0,0);
int count = 1;
while(true){
if(count>2000001){
break;
}
if(!sum[count]){
System.out.println(count);
break;
}
else{
count++;
}
}
}
static void dfs(int start, int value){
if(start>=N){
return;
}
for(int i=start; i<N; i++){
if(!visit[i]) {
visit[i]=true;
value=value+arr[i];
if(value<=2000000) {
sum[value] = true;
}
dfs(i+1,value);
value-=arr[i];
visit[i]=false;
}
}
}
}