반응형
https://www.acmicpc.net/problem/2470
2470번: 두 용액
첫째 줄에는 전체 용액의 수 N이 입력된다. N은 2 이상 100,000 이하이다. 둘째 줄에는 용액의 특성값을 나타내는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 수들은 모두 -1,000,000,000 이상 1,000,00
www.acmicpc.net
1. 문제설명
두 용액의 합이 가장 0에 가까울 때의 두 용액의 값을 출력하는 문제이다.
단순하게 나올 수 있는 모든 용액의 합을 구하면 시간복잡도가 O(N^2)이 되기 때문에 틀린다.
우선 모든 용액의 값을 받아 정렬하고
가장 작은값과 가장 큰값을 start 지점과 end지점으로 두어서 더해본다.
v[start] + v[end] > 0 이라면 두 용액의 합이 0에 가까워지기 위해서
두용액의 합을 줄여야한다.
이 때 이미 모든 용액은 오름차순으로 정렬되어 있기 때문에 두 용액의 합을 줄이기 위해서는
end의 값을 줄여야한다
반대로 v[start] + v[end] < 0 일 때는 두 용액의 합이 0에 가까워지기 위해
두 용액의 합을 키워야하므로
start의 값을 키워야한다.
이 과정을 start < end 인 동안 반복한다.
두 용액은 다른 용액을 사용해야 하기 때문에 start==end가 되어서는 안된다.
이 과정을 반복하면 abs(v[start] + v[end])가 최소가 되는 지점을 찾을 수 있다.
이를 코드로 옮기면 된다.
정렬할 때 시간복잡도 O(NlogN)
start, end를 찾는 과정 O(N) 이므로
O(NlogN)으로 이 문제를 해결 할 수 있다.
2.문제풀이코드
#include <bits/stdc++.h>
using namespace std;
int n;
vector<int> v;
int main(){
ios::sync_with_stdio(0); cin.tie(0);
cin >> n;
for(int i=0; i<n; i++){
int num;
cin >> num;
v.push_back(num);
}
sort(v.begin(), v.end());
int st = 0, en = n-1;
int ans_val = INT_MAX;
int ans1, ans2;
while(st < en){
int sum = v[st] + v[en];
if(sum==0) {
cout << v[st] << ' ' << v[en];
return 0;
}
if(ans_val >= abs(sum)){
ans_val = abs(sum);
ans1 = v[st];
ans2 = v[en];
}
//두합이 0보다 크다면 en의 값을 줄여야하고 0보다 작다면 st의 값을 증가시킨다.
if(sum > 0){
en--;
}
else{
st++;
}
}
cout << ans1 << ' ' << ans2;
return 0;
}
반응형
'Algorithm > problem' 카테고리의 다른 글
백준 1325번 : 효율적인 해킹 -BFS, DP를 쓰면 안되는 이유 C++ (0) | 2022.07.02 |
---|---|
백준 16563번 : 어려운 소인수분해 - 에라토스테네스의 체 C++ (0) | 2022.06.29 |
[백준] 2401 - 최대 문자열 붙여넣기 KMP + DP Cpp 코드 (0) | 2022.06.27 |
[백준] 4354번 : 문자열 제곱 - 자세한 설명 포함 KMP 알고리즘 응용 (0) | 2022.06.25 |
백준 1786번 : 찾기 - KMP 알고리즘 (0) | 2022.06.24 |