문제 이해 단계
문제 자체는 굉장히 단순하다.
운동을 2개씩 짝지어하는데,
하나가 남을 경우 그건 따로 진행한다.
이런 식으로 진행하는데
2개의 숫자의 합과 남은 하나의 숫자를
최소 값으로 하는 수를 찾는 것이다.
문제 접근 단계
이 문제의 포인트는
주어진 운동의 수가 홀수인가 짝수 인가로 나뉜다.
운동 수가 짝수라면,
무조건 두 수의 합이 최소가 되는 값을 찾아야 한다.
하지만 홀수라면 무조건 하나가 남게 되기 때문에,
최솟값을 산출하기 위해 남을 1개의 수를 찾아야 한다.
일단 최솟값이 되기 위한 방법을 생각해 보자.
당연히 (높은 수) + (낮은 수)를 하는 것이
값을 최소화하는 방법이다.
(가장 높은 수 + 가장 낮은 수), (그다음 높은 수 + 그다음 낮은 수)...
이런 식으로 모두 계산했을 때
가장 높은 값이 답이 된다.
하지만 홀수라면 수가 하나 남게 되는데,
이 수는 가장 높은 수가 되어야 한다.
왜냐하면 가장 높은 수를 빼둬야
(높은 수 + 낮은 수) 연산을 할 때
값을 최소로 할 수 있기 때문이다.
즉,
짝수일 경우 : 답 = (높은 수 + 낮은 수)의 최댓값
홀수 일 경우 : 가장 높은 수를 제외해 두고 (높은 수 + 낮은 수) 연산
을 하고 가장 높은 수와 연산 값의 최댓값이 답이 된다.
문제 구현 단계
sort(list.begin(), list.end());
answer = list[list.size() - 1];
if (list.size() % 2 != 0 && list.size() != 1) list.erase(list.end() - 1);
int sPos = 0;
int ePos = list.size() - 1;
while (sPos < ePos) {
long value = list[sPos] + list[ePos];
if (value > answer)
answer = value;
sPos++;
ePos--;
}
가장 주요한 코드이다.
먼저 입력받은 값들을 오름차순으로 정렬한다.
그 이후 최댓값인 마지막 배열로 설정해 두고,
%2를 통해 값이 홀수라면 마지막 값을 빼준다.
리스트가 1개일 경우,
리스트를 하나 빼주는 과정에서
오류가 날 수 있기 때문에, 1인 경우도 제외했다.
이후 sPos -> 가장 낮은 값
ePos -> 가장 높은 값 인덱스로 지정하여
1씩 더하고 빼주었다.
이는 그다음 높은 값과 그다음 낮은 값을 받아
서 서로 더해주는 작업을 뜻한다.
그리고 그게 answer보다 크다면
정답을 answer로 처리해 준다.
사실 이 문제는 이 코드가 전부이기 때문에
더 이상 정리할 것이 없다.
아래에 전체코드를 올려두고 마무리하겠다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
cin.tie(NULL);
cout.tie(NULL);
ios::sync_with_stdio(false);
int N;
long answer;
vector<long> list;
cin >> N;
while (N-- > 0) {
long value;
cin >> value;
list.push_back(value);
}
// 오름차순 정렬
sort(list.begin(), list.end());
answer = list[list.size() - 1];
if (list.size() % 2 != 0 && list.size() != 1) list.erase(list.end() - 1);
int sPos = 0;
int ePos = list.size() - 1;
while (sPos < ePos) {
long value = list[sPos] + list[ePos];
if (value > answer)
answer = value;
sPos++;
ePos--;
}
cout << answer;
}
vector와 answer을 long으로 받은 이유는 조건에서
근손실을 나타내는 값이 10^18이기 때문에
int로 받기에는 오버플로우가
발생할 가능성이 생기기 때문이다.
시행착오
쉬운 문제였기 때문에 시행착오는 따로 없었던 것 같다.