알고리즘/BOJ
[백준/C++] #1744 수묶기 (Greedy)
persi0815
2025. 3. 26. 12:12
문제
https://www.acmicpc.net/problem/1744
풀이 (37m / 한번에 x)
수들끼리 짝지어서 곱해 더할 수도 있고, 그냥 더할 수도 있는데, 합이 최대가 되도록 해야했다.
생각났던 로직 순서대로
- 가장 큰 양수부터 시작해서 두개씩 짝지어서 곱해서 더함
- 양수의 개수가 홀수라면 남은 양수는 그냥 더함
- 1은 다른 양수랑 곱해서 더하기보다 그냥 더하는게 더 커지니 따로 그냥 더함
- 0도 있고 홀수도 있다면, 0 개수만큼 가장 작은 홀수들 부터 없애기
+) 음수가 2개 이상이라면 0이랑 상쇄시키기보다 일단 가장 작은 홀수들부터 두개씩 곱해서 양수 만들기
+) 음수가 홀수개이고, 0이 있다면 마지막으로 가장 큰 음수는 0이랑 상쇄시키기. 0이 없다면 그냥 더하기
생각보다 예외 케이스들이 바로바로 생각나지 않았던 문제였다. (마지막 + 부분은 생각이 너무 늦게남..)
앞으로는 코드 짜기 전에 예외 케이스를 좀 더 생각해보자!!
코드
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/*
수 묶기
- 양수는 큰 수끼리 곱
- 1은 그냥 더함
- 음수는 작은 수끼리 곱
- 음수 1개 남았고 0이 있으면 곱해서 무시
*/
int n;
int res = 0;
vector<int> v;
int main(){
cin >> n;
for(int i = 0; i < n; i++){
int nn; cin >> nn;
v.push_back(nn);
}
sort(v.begin(), v.end(), greater<int>()); // 내림차순
int idx = 0;
// 양수 중 1보다 큰 애들끼리 곱
while(idx + 1 < v.size() && v[idx] > 1 && v[idx + 1] > 1){
res += v[idx] * v[idx + 1];
idx += 2;
}
// 1 이상 양수는 더함
while(idx < v.size() && v[idx] >= 1){
res += v[idx];
idx++;
}
// 나머지 숫자들 (0 이하)
vector<int> sub(v.begin() + idx, v.end());
vector<int> negatives;
bool hasZero = false;
for (int num : sub) {
if (num == 0) hasZero = true;
else if (num < 0) negatives.push_back(num);
}
sort(negatives.begin(), negatives.end()); // 작은 음수부터
int i = 0;
// 가장 작은 음수끼리 곱함
while (i + 1 < negatives.size()) {
res += negatives[i] * negatives[i + 1];
i += 2;
}
// 음수 1개 남았을 경우
if (i == negatives.size() - 1) {
if (!hasZero) {
res += negatives[i]; // 0 없으면 그냥 더함
}
// 0 있으면 곱해서 무시 (아무 것도 안 더함)
}
cout << res;
}