https://www.acmicpc.net/problem/2470
목적
용액의 특성값들이 N개 주어질 때, 특성값을 2개를 더해 절대값이 0에 가장 가까운 용액의 특성값들을 구하자.
접근법
투 포인터 알고리즘으로 구현이 가능하다.(완전 탐색이나 이분 탐색보다 빠르고 간단하다.) 투 포인터 알고리즘은 다음과 같이 정렬된 배열이 있다면, 배열의 처음과 끝을 가리키는 L과 R을 서로가 가까워지도록 이동하는 방식으로 동작한다.
초기 상황을 제외하고 최대 N-2번의 포인터 이동이 있는데, 각 턴마다 두 포인터가 가리키는 수의 합이 0에 수렴하도록 한 개의 포인터를 이동해야 한다. 즉, 수의 합이 양수일 때는 R을 이동하여 합을 줄여주고, 음수일 때는 L을 이동하여 합을 늘려준다. 동시에 절대값의 최소값을 갱신해주면 된다.
이 과정을 이차원 배열 형태로 보면 다음과 같다. 처음 (A,F)지점 부터 (A,E)를 거쳐 (C,D)지점 까지 이동하며 N-1번의 탐색으로 답을 구할 수 있게 된다. 포인터 이동 규칙에 따라 건너 뛰게 되어 탐색되지 않은 지점의 값은 양의 무한대나 음의 무한대로 발산하므로 굳이 볼 필요가 없는 것이다.
#include<bits/stdc++.h>
#define f(i,l,r) for(int i=l;i<r;++i)
using namespace std;
int n,a[(int)1e5],s[2];
void sol(){
int l=0,r=n-1,mn=2e9;
while(l<r){
int sum=a[l]+a[r];
int tmp=abs(sum);
if(mn>tmp)s[0]=l,s[1]=r,mn=tmp;
if(!sum)return;
sum>0?--r:++l;
}
}
int main(){
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n;
f(i,0,n)cin>>a[i];
sort(a,a+n);
sol();
cout<<a[s[0]]<<' '<<a[s[1]];
return 0;
}
문제 설명과 코드에 대한 피드백은 언제나 환영합니다.
다양한 의견 댓글로 남겨주세요.
'Problem Solving > BOJ 백준' 카테고리의 다른 글
[ BOJ 백준 1126번 - 같은 탑] 해설 및 코드 (0) | 2020.06.29 |
---|---|
[ BOJ 백준 2473번 - 세 용액 ] 해설 및 코드 (0) | 2020.04.16 |
[ BOJ 백준 17780번 - 새로운 게임 ] 해설 및 코드 (0) | 2020.04.12 |
[ BOJ 백준 1328번 - 고층 빌딩 ] 해설 및 코드 (6) | 2020.04.07 |
[ BOJ 백준 13398번 - 연속합 2 ] 해설 및 코드 (0) | 2020.03.30 |