비슷한 유형의 문제들이 많은데 이 문제는 고생해서 풀었다.
일단 N이 40이니 2^40 이면 1초 안에 들어오지 못하니
2^20으로 두번 한다는 발상 조차 떠올리지 못해 다른 블로그들의 도움을 받았다
배열을 반으로 쪼개서 (left와 right로 나누겠다)
각각 left와 right에 들어 갈 수 있는 부분수열들을 집어 넣으면 되는데
재귀호출을 이용한다
1
2
3
4
5
6
7
8
|
public static void dfs(int level, int end, int sum ,ArrayList<Integer>list) {
if(level == end) {
list.add(sum);
return ;
}
dfs(level+1,end,sum+arr[level],list);
dfs(level+1,end,sum,list);
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
left의 경우 level은 0부터 시작하며 end는 n/2 이다 (left의 범위는 0~n/2)
right의 경우 level은 n/2부터 시작하며 end는 n이다 (right의 범위는 n/2~n)
6번째 줄의 경우 지금 단계의 배열값을 더하는 것
7번줄의 경우 지금 단계의 배열값을 더하지 않고 인덱스만 (level) 증가 시키는것
결국 이렇게 하면 정해진 모든 범위의 값을 구할 수 있다.
ex) arr[1] = 1, arr[2] =2, arr[3] = 3
6번째 줄은 level=1 , sum=arr[1] point 1
7번째 줄은 level =1 sum =0 point 2
point 1 에서 호출된 함수가 실행 되면 level = 2 ,sum = arr[1]
6번째 줄 실행하고 호출된 함수의 결과는 level=3 sum = arr[1]+arr[2]
7번째 줄 실행하고 호출된 함수의 결과는 level=3 sum = arr[1] (arr[2]를 안더해주고 넘어감)
point 2에서 호출된 함수가 실행되면 level=2 , sum=0
6번째 줄 실행하고 호출된 함수의 결과는 level=2 sum = arr[2]
7번째 줄 실행하고 호출된 함수의 결과는 level=2 sum= 0
이런식으로 반복되면 결국 모든 값이 다 나오는데 7번째줄 코드 즉 아무것도 더하지 않고 level만 올라가는 것도
결과에 포함됨으로 공집합인 0 의 값 또한 리스트에 들어 갈 수 있다 그러므로 문제서 주어진 s가 0 이면 따로 1개를 빼줘야 한다.
그 후 left와 right에 들어 갈 수 있는 합들을 다 담은 다음 투포인터 알고리즘을 이용해서 진행 하면 되는데
두개의 리스트 다 오름차순 정렬을 한 다음
left는 0부터 right는 right.size()-1 부터 투포인터를 진행하면 된다
전체 코드
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
public class Main {
static int n,s;
static long cnt=0;
static int arr[];
static ArrayList<Integer> left = new ArrayList<>();
static ArrayList<Integer> right = new ArrayList<>();
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] t = br.readLine().split(" ");
n = Integer.parseInt(t[0]);
s = Integer.parseInt(t[1]);
arr = new int[n];
String[] input = br.readLine().split(" ");
for(int i=0; i<n; i++) {
arr[i] = Integer.parseInt(input[i]);
}
dfs(0,n/2,0,left);
dfs(n/2,n,0,right);
int left_idx =0;
long left_cnt =0;
long right_cnt = 0;
if(left_sum+right_sum == s) {
left_idx++;
left_cnt++;
}
right_cnt++;
right_idx--;
}
cnt+=left_cnt*right_cnt;
}
else if(left_sum+right_sum>s) {
right_idx--;
}
else if(left_sum+right_sum<s) {
left_idx++;
}
}
if(s==0) {
cnt-=1;
}
System.out.println(cnt);
}
public static void dfs(int level, int end, int sum ,ArrayList<Integer>list) {
if(level == end) {
list.add(sum);
return ;
}
dfs(level+1,end,sum+arr[level],list);
dfs(level+1,end,sum,list);
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
'알고리즘' 카테고리의 다른 글
[백준 7453] 합이 0인 네 정수 -JAVA // le_effort// (1) | 2020.03.03 |
---|---|
[백준 13913] 숨바꼭질4 -JAVA // le_effort// (0) | 2020.02.28 |
[백준 2143] 두 배열의 합 - JAVA // le_effort// (0) | 2020.02.28 |
[백준 1644] 소수의 연속합 자바 //le_effort// (0) | 2020.02.28 |
[백준 1806] 부분합 자바 //le_effort// (0) | 2020.02.28 |