https://www.acmicpc.net/problem/2473
2473번: 세 용액
첫째 줄에는 전체 용액의 수 N이 입력된다. N은 3 이상 5,000 이하의 정수이다. 둘째 줄에는 용액의 특성값을 나타내는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 수들은 모두 -1,000,000,000 이상
www.acmicpc.net
2467번 문제의 응용으로, 입력받은 배열을 정렬한 뒤 배열의 각 인덱스 i에 대해 범위 [i + 1, (배열의 사이즈)) 구간에 대해 투 포인터를 반복하면 답을 얻을 수 있다.
#include <algorithm>
#include <cstdio>
#include <tuple>
using namespace std;
typedef long long ll;
#define MAX_N 5000
int N;
int liq[MAX_N];
tuple<int, int, int> t = {0, 1, 2};
// sum(): 인자로 세 인덱스를 주면 liq에서 각 인자를 참고, 주지 않는다면 t를 참조
// liq에서 참조한 세 인덱스를 이용해 값을 찾아 모두 더해 반환
ll sum_(int a, int b, int c) { return (ll)liq[a] + (ll)liq[b] + (ll)liq[c]; }
ll sum_() { return sum_(get<0>(t), get<1>(t), get<2>(t)); }
// 배열에서 p 이후의 인덱스에 한해 투 포인터 실행
void two_pointer(int p) {
// l, r: 투 포인터에서 참조할 인덱스
int l = p + 1, r = N - 1;
while (l < r) {
// 세 용액의 합이 기존 용액의 합보다 0에 가깝다면 갱신
if (llabs(sum_(p, l, r)) < llabs(sum_())) t = {p, l, r};
// 투 포인터 실행
(sum_(p, l, r) < 0) ? l++ : r--;
}
}
int main() {
// 용액의 수와 각 용액의 특성값을 입력받은 뒤
scanf("%d", &N);
for (int i= 0; i < N; i++) scanf("%d", liq + i);
// 특성값을 오름차순으로 정렬
sort(liq, liq + N);
// 인덱스 하나를 잡고 투 포인터 실행
for (int i = 0; i < N; i++) two_pointer(i);
// 투 포인터 실행 결과를 반환
printf("%d %d %d\n", liq[get<0>(t)] , liq[get<1>(t)], liq[get<2>(t)]);
return 0;
}
'알고리즘 > 문제 풀이' 카테고리의 다른 글
2504번: 괄호의 값 (0) | 2021.12.17 |
---|---|
2475번: 검증수 (0) | 2021.12.17 |
2468번: 안전 영역 (0) | 2021.12.16 |
2467번: 용액 (0) | 2021.12.16 |
2448번: 별 찍기 - 11 (0) | 2021.12.16 |