2020/07/13 - [알고리즘 공부] - boj 1208: 부분집합의 합2

 

boj 1208: 부분집합의 합2

문제의 크기가 클 경우에는 문제를 절반으로 나누어서 문제를 푼 후 두 개를 합치는 방식을 이용한다. 배열의 크기가 N인 집합이 있을 때 부분집합의 합이 M이 나오는 갯수를 찾는 문제이다. 이 �

sysgongbu.tistory.com

위 글과 마찬가지 방법으로 풀면 된다.

 

크기 N이 주어졌을 때, 배열 A, B, C, D가 주어지면

A[a]+B[b]+C[c]+D[d]==0인 a, b, c, d의 쌍을 구하는 문제이다.

 

4중 for문을 돌리면 O(N^4)만에 풀 수 있지만,

A[a]+B[b]와 C[c]+D[d]를 순차적으로 구한 뒤 합이 0인지 찾는다면 O(N^2)만에 풀 수 있다.

 

import java.util.*;
import java.io.*;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();

		long A[] = new long[n];
		long B[] = new long[n];
		long C[] = new long[n];
		long D[] = new long[n];
		for (int i = 0; i < n; i++) {
			A[i] = in.nextLong();
			B[i] = in.nextLong();
			C[i] = in.nextLong();
			D[i] = in.nextLong();
		}

		long left[] = new long[n * n];
		long right[] = new long[n * n];
		int index = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				left[index] = A[i] + B[j];
				right[index] = C[i] + D[j];
				index++;
			}
		}

		Arrays.sort(left);
		Arrays.sort(right);

		long ans = 0;
		int leftIndex = 0;
		int rightIndex = n * n - 1;
		while (leftIndex < n * n && rightIndex >= 0) {
			long leftSum = left[leftIndex];
			long rightSum = right[rightIndex];
			if (leftSum + rightSum == 0) {
				long leftSame = 0;
				long rightSame = 0;
				while (leftIndex < n * n && leftSum == left[leftIndex]) {
					leftIndex++;
					leftSame++;
				}
				while (rightIndex >= 0 && rightSum == right[rightIndex]) {
					rightIndex--;
					rightSame++;
				}
				ans += leftSame * rightSame;
			} else if (leftSum + rightSum > 0) {
				rightIndex--;
			} else {
				leftIndex++;
			}
		}
		System.out.println(ans);
	}
}

'알고리즘 공부 > boj' 카테고리의 다른 글

boj 2143: 두 배열의 합  (0) 2020.07.15
boj 2632: 피자판매  (0) 2020.07.15
boj 1208: 부분집합의 합2  (0) 2020.07.13
boj 1956: 운동  (0) 2020.07.10
boj 1507: 궁금한 민호  (0) 2020.07.10

+ Recent posts