안녕하세요.
여행벌입니다.
오늘은 ACM-ICPC 2012 예선전 문제인 'Canoe Racer' 문제를 다뤄보겠습니다.
[문제해석]
1. 특정 숫자 K 와 n 개 씩 4개의 숫자 배열이 주어졌을 때, 4개의 배열에서 하나씩 숫자를 뽑아 합했을 때, 특정 숫자 K과 가장 근접한 경우를 출력하라. (K과 가장 근접한 숫자가 2개 이상일 때는 더 작은 숫자를 출력하라.)
[알고리즘설계]
n 개 씩 4개의 숫자 배열을 각각 A,B,C,D 배열이라고 하자.
n이 최대 1000 이므로, A,B,C,D 배열에서 4중 for 문으로 1개씩 뽑아 모든 경우의 수를 다 구한다면, O(n^4)으로 당연히 시간 초과에 걸릴 것이다.
따라서, 우리는 A,B / C,D 배열을 2개씩 합쳐서 AB / CD 배열을 따로 만들고, 그 배열을 순회하며 답을 찾아줄 것이다.
또, AB배열을 순회하며, CD 배열에 있는 원소와의 합이 K와 근접한 숫자를 찾아야하는데, Linear Search 보다는 AB / CD 배열을 Sorting 한 후, Binary Search 를 이용해 답을 찾아줄 것이다.
그렇다면, O(n^4)의 복잡도가 O(n^2)으로 낮아진다.
#include<cstdio>
#include<algorithm>
int map[4][1000];
int ab[1000000];
int cd[1000000];
using namespace std;
int abs(int n) {
if (n < 0)
return -n;
return n;
}
int main(void) {
int test_case;
scanf("%d", &test_case);
for (int i = 0; i < test_case; i++) {
int answer, ninput;
scanf("%d %d", &answer, &ninput);
for (int j = 0; j < 4; j++)
for (int k = 0; k < ninput; k++)
scanf("%d", &map[j][k]);
for (int j = 0; j < ninput; j++)
for (int k = 0; k < ninput; k++){
ab[ninput * j + k] = map[0][j] + map[1][k];
cd[ninput * j + k] = map[2][j] + map[3][k];
}
sort(ab, ab + ninput * ninput);
sort(cd, cd + ninput * ninput);
int flag = 0, total_result = 999999999;
int length = ninput * ninput;
// Binary Search
for (int j = 0; j < length; j++) {
int result = 999999999;
int left = 0;
int right = length - 1;
while (left <= right) {
int mid = (left + right) / 2;
int temp = ab[j] + cd[mid];
if (temp == answer) {
printf("%d\n", answer);
flag = 1;
break;
}
else if (temp < answer) {
left = mid + 1;
}
else{
right = mid - 1;
}
if (abs(answer - result) > abs(answer - temp))
result = temp;
else if(abs(answer - result) == abs(answer - temp))
result = min(result, temp);
}
if (flag)
break;
if (abs(answer - result) < abs(answer - total_result))
total_result = result;
else if(abs(answer - result) == abs(answer - total_result))
total_result = min(result, total_result);
}
if (flag)
continue;
printf("%d\n", total_result);
}
}
배열을 2개씩 합쳐주면서 복잡도를 완전히 낮춰줄 수 있는데, 기존에 풀었던 문제와 유사해서 쉽게 문제를 해결할 수 있었다.
'Problem Solving > ICPC' 카테고리의 다른 글
[ACM-ICPC][BOJ] 9012 - Parenthesis (0) | 2019.08.08 |
---|---|
[ACM-ICPC][BOJ] 9009 - Fibonacci Numbers (0) | 2019.08.05 |
[ACM-ICPC][BOJ] 16702 - The Silence of the Lamp (0) | 2019.08.01 |
[ACM-ICPC][BOJ] 8901 - Chemical Products (0) | 2019.08.01 |
[ACM-ICPC][BOJ] 10448 - Eureka Theorem 문제풀이 (0) | 2019.07.31 |