백준

[백준_1182번] 부분수열의 합

빙수빈수 2021. 8. 5. 14:47

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

 

1182번: 부분수열의 합

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

www.acmicpc.net

[문제]

 N개의 정수로 이루어진 수열이 있을 때, 크기가 양수인 부분수열 중에서 그 수열의 원소를 다 더한 값이 S가 되는 경우의 수를 구하는 프로그램을 작성하시오.

 

[입력 조건]

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

 

[코드]

import java.util.*;

public class BaekJoon_1182 {
	static int count=0,n,s;
	static int[] arr;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		s=sc.nextInt();
		arr=new int[n];
		
		for(int i=0;i<n;i++)
			arr[i]=sc.nextInt();
		
		dfs(0,0);
		
		// 합이 0일 경우에는 공집합도 포함되므로 -1 해준 값을 출력한다.
		if(s==0)
			count-=1;
		
		System.out.println(count);
	}
	public static void dfs(int depth, int sum) {
		if(depth==n) {
			if(sum==s)
				count++;
			return;
		}
		
		/*
		 * 부분수열을 구하는 방법으로는 지금 위치의 원소를
		 * 선택하는 방법과, 선택하지 않는 방법이 있다. 
		 */
		dfs(depth+1,sum); // 지금 위치의 원소를 빼고 구하는 방법
		dfs(depth+1,sum+arr[depth]); // 지금 위치의 원소를 포함하여 구하는 방법
	}
}

 

[고찰]

 이번 문제는 이전에 풀었던 백트래킹 문제들과 비슷하지만 구조가 살짝 다르다. 백트래킹을 사용하여 만들어질 수 있는 모든 부분수열을 확인해서 풀어야하는데, 이때 부분수열을 구하는 방법은 지금 위치의 원소를 선택하는 방법과 선택하지 않는 방법이 있다. 

 처음에는 숫자를 선택하는 과정에서 for문과 방문체크 배열을 사용했는데 해당 문제에서는 그럴 필요가 없다. 이전 문제에서는 선택되는 원소가 같아도 각 자리의 원소가 무엇이냐에 따라 다른 값으로 간주했지만 해당 문제는 선택되는 순서와 상관없이 무엇을 선택했느냐가 중요한 문제이기 때문이다. 따라서 첫번째 원소를 선택할 것인지 말것인지만 정하면 된다.

 백트래킹을 사용해하는 문제라는것은 파악했지만 기존 백트래킹 문제와는 살짝 달라 다른 사람의 코드를 참고한 문제였다. 이렇게 응용된 문제도 해결할 수 있어야하는데 그러지 못해 아쉬웠다.

'백준' 카테고리의 다른 글

[백준_2485번] 가로수  (0) 2021.08.05
[백준_9095번] 1, 2, 3 더하기  (0) 2021.08.05
[백준_5430번] AC  (0) 2021.08.05
[백준_1158] 요세푸스 문제  (0) 2021.08.05
[백준_6603번] 로또  (0) 2021.08.04