[백준 2470번 C/C++] 두 용액
[백준 2470번 C/C++] 두 용액
https://www.acmicpc.net/problem/2470
해결방안
투 포인터
처음 시도한 코드
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Solution
{
int first, second, ave;
Solution(int a, int b, int c)
{
first = a;
second = b;
ave = c;
}
bool operator<(const Solution& s){
return ave < s.ave;
}
};
int n;
vector<int> v; // 주어진 용액을 담는 배열
vector<Solution> result; // 첫번째 용액, 두번째 용액, 두 용액 섞었을때 pH 절대값을 담는 배열
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
v.resize(n);
for(int i=0; i<n; i++){
cin >> v[i];
}
sort(v.begin(), v.end());
int left = 0;
int right = n - 1;
while (left < right)
{
int sumSol = v[left] + v[right];
if (sumSol == 0){
cout << v[left] << " " << v[right] << "\n";
return 0;
}
if (sumSol > 0) {
right--;
}
if (sumSol < 0 && right < n - 1){
result.push_back({ v[left], v[right + 1], abs(sumSol) });
result.push_back({ v[left], v[right], abs(sumSol) });
left++;
right++;
}
}
sort(result.begin(), result.end());
cout << result[0].first << " " << result[0].second << "\n";
return 0;
}
시간초과
정답 코드
처음 시도한 코드를 수정한 정답 코드. Ver1.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Solution
{
int first, second, ave;
Solution(int a, int b, int c)
{
first = a;
second = b;
ave = c;
}
bool operator<(const Solution& s){
return ave < s.ave;
}
};
int n;
vector<int> v; // 주어진 용액을 담는 배열
vector<Solution> result; // 첫번째 용액, 두번째 용액, 두 용액 섞었을때 pH 절대값을 담는 배열
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
v.resize(n);
for(int i=0; i<n; i++){
cin >> v[i];
}
sort(v.begin(), v.end());
int left = 0;
int right = n - 1;
while (left < right)
{
int sumSol = v[left] + v[right];
result.push_back({v[left], v[right], abs(sumSol)});
if (sumSol == 0){
cout << v[left] << " " << v[right] << "\n";
return 0;
}
if (sumSol > 0)
right--;
else // sumSol < 0
left++;
}
sort(result.begin(), result.end());
cout << result[0].first << " " << result[0].second << "\n";
return 0;
}
다른 풀이. Ver2.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int n;
vector<int> v; // 주어진 용액을 담는 배열
int resultSumSol = 2147000000;
int firstSol, secondSol;
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
v.resize(n);
for(int i=0; i<n; i++){
cin >> v[i];
}
sort(v.begin(), v.end());
int left = 0;
int right = n - 1;
while (left < right)
{
int sumSol = v[left] + v[right];
if (sumSol == 0){
cout << v[left] << " " << v[right] << "\n";
return 0;
}
if (abs(sumSol) < resultSumSol) {
resultSumSol = abs(sumSol);
firstSol = v[left];
secondSol = v[right];
}
if (sumSol > 0)
right--;
else
left++;
}
cout << firstSol << " " << secondSol << "\n";
return 0;
}
고민한 부분
아래는 처음 시도해서 실패한 부분
resultSumSol의 초기값을 resultSumSol = abs(v[left] + v[right]);로 설정하였다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int n;
vector<int> v; // 주어진 용액을 담는 배열
int resultSumSol;
int firstSol, secondSol;
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
v.resize(n);
for(int i=0; i<n; i++){
cin >> v[i];
}
sort(v.begin(), v.end());
int left = 0;
int right = n - 1;
resultSumSol = abs(v[left] + v[right]);
while (left < right)
{
int sumSol = v[left] + v[right];
if (sumSol == 0){
cout << v[left] << " " << v[right] << "\n";
return 0;
}
if (abs(sumSol) < resultSumSol) {
resultSumSol = abs(sumSol);
firstSol = v[left];
secondSol = v[right];
}
if (sumSol > 0)
right--;
else // sumSol < 0
left++;
}
cout << firstSol << " " << secondSol << "\n";
return 0;
}
첫 번째 코드에서는 resultSumSol을 용액들의 처음과 끝 값의 합으로 초기화했고, 아래의 두 번째 코드에서는 매우 큰 값을 이용하여 초기화했습니다.
첫 번째 코드에서 문제가 발생하는 이유는
용액들이 모두 양수거나 모두 음수인 경우, 처음과 끝 값의 합은 실제 최소값이 아닐 수 있다. 따라서 이를 기준으로 비교하는 것은 올바르지 않다.
만약 입력된 용액들 중 어느 하나라도 절대값이 resultSumSol보다 크면, 그 용액을 사용한 조합은 절대로 선택되지 않게 된다. 즉, 첫 번째와 마지막 값의 합보다 큰 절대값을 가진 용액이 있는 경우, 그 용액을 포함하는 올바른 답을 찾을 수 없게 된다.
반면에 아래의 두 번째 코드에서는 resultSumSol를 매우 큰 값으로 초기화했다. 이렇게 함으로써 위에서 언급한 문제점들을 피할 수 있으며, 모든 가능한 조합들 중 최소값을 찾아낼 수 있다.
따라서 결과적으로 첫 번째 방식은 특정 입력에 대해 잘못된 결과를 출력할 가능성이 있으며, 두 번째 방식은 모든 입력에 대해 올바른 결과를 출력하게 된다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int n;
vector<int> v; // 주어진 용액을 담는 배열
int resultSumSol = 2147000000;
int firstSol, secondSol;
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
v.resize(n);
for(int i=0; i<n; i++){
cin >> v[i];
}
sort(v.begin(), v.end());
int left = 0;
int right = n - 1;
while (left < right)
{
int sumSol = v[left] + v[right];
if (sumSol == 0){
cout << v[left] << " " << v[right] << "\n";
return 0;
}
if (abs(sumSol) < resultSumSol) {
resultSumSol = abs(sumSol);
firstSol = v[left];
secondSol = v[right];
}
if (sumSol > 0)
right--;
else
left++;
}
cout << firstSol << " " << secondSol << "\n";
return 0;
}
'⭐ 코딩테스트 > 백준' 카테고리의 다른 글
[백준 7576번 C/C++] 토마토 (0) | 2023.11.06 |
---|---|
[백준 1806번 C/C++] 부분합 (0) | 2023.10.31 |
[백준 3273번 C/C++] 두 수의 합 (1) | 2023.10.29 |
[백준 11054번 C/C++] 가장 긴 바이토닉 부분 수열 (0) | 2023.10.28 |
[백준 1269번 C/C++] 대칭 차집합 (0) | 2023.10.25 |
댓글
이 글 공유하기
다른 글
-
[백준 7576번 C/C++] 토마토
[백준 7576번 C/C++] 토마토
2023.11.06 -
[백준 1806번 C/C++] 부분합
[백준 1806번 C/C++] 부분합
2023.10.31 -
[백준 3273번 C/C++] 두 수의 합
[백준 3273번 C/C++] 두 수의 합
2023.10.29 -
[백준 11054번 C/C++] 가장 긴 바이토닉 부분 수열
[백준 11054번 C/C++] 가장 긴 바이토닉 부분 수열
2023.10.28