도서관 << 문제 클릭!
세준이와 책들의 위치가 0이다. 책들의 원래 위치가 주어질 때 책을 모두 제자리에 놔둘 때 드는 최소 걸음 수를 계산해라.
입력
: 책의 개수 N, 한 번에 들 수 있는 책의 개수 M (1 <= N,M <= 50)
: 책의 위치 (0 없음, 절댓값은 10,000보다 작거나 같은 정수)
출력
: 최소 걸음 수
조건
: 1 걸음 = 좌표 1칸
: 책의 위치는 모두 정수
: 책을 모두 제자리에 놔두면 다시 0으로 돌아올 필요가 없다. == 가장 거리가 먼 위치는 돌아오지 않아도 된다.
: 세준이가 책을 한 번 두는데 왕복한다 == 가장 거리가 먼 곳은 왕복하면 안 된다.
: 세준이가 책을 한 번 두는데 거리가 먼 곳을 기준으로 왕복한다.
== 이때 책의 개수가 M권을 기준으로 왕복한다.
== 이때 책의 위치가 적은 곳 부터 왕복하는 것은 그리디가 아니다.
✅ 한 번 책을 두는데 가장 거리가 먼 곳 부터 M개 씩 책을 정리
include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
int N, M;
cin >> N >> M;
vector<int> pos; // 양수 배열
vector<int> neg; // 음수 배열
int sum = 0;
int temp = 0;
for (int i = 0; i < N; i++) {
cin >> temp;
if (temp > 0) {
pos.push_back(temp); // 양수 추가
}
else {
neg.push_back(temp); // 음수 추가
}
}
sort(neg.begin(), neg.end()); // 오름차순
sort(pos.begin(), pos.end());
int i = 0;
while (i < neg.size()) {
sum -= 2*neg[i]; // 절댓값을 더해줘야 하니까
i += M; // M만큼 증가
}
int j = pos.size()-1; // 인덱스는 i-1번째니까
while (j > 0) {
sum += 2*pos[j]; // 더해줌
j -= M;
}
if (-neg.front() > pos.back()) {
cout << sum + neg.front();
}
else {
cout << sum - pos.back();
}
return 0;
}
✅문제 원인
예제 중 1 50 1인 경우를 테스트 해보니 다음과 같은 에러가 떴다.
즉, empty vector의 front()를 호출하고 있다는 것!
물론 if와 else를 이용해서 문제를 해결할 수 있지만, 효율적이지 않다는 판단하게 코드를 바꾸기로 했다.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
int N, M;
cin >> N >> M;
vector<int> v; // 전체 배열
int sum = 0;
int temp = 0;
int count = 0;
for (int i = 0; i < N; i++) {
cin >> temp;
v.push_back(temp); // 양수 추가
if (temp < 0) {
count++; // 음수 개수 count
}
}
sort(v.begin(), v.end()); // 내림차순
for (int i = 0; i < count; i += M) {// M만큼 증가
sum -= 2*v[i]; // 절댓값을 더해줘야 하니까
}
// 인덱스는 i-1번째니까
for(int i = v.size()-1; i>= count;i -= M){
sum += 2 * v[i]; // 더해줌
}
if (abs(v.front()) < abs(v.back())) { //절댓값으로 바로 비교
cout << sum - abs(v.back());
}
else {
cout << sum - abs(v.front());
}
}
오히려 시간도 단축되고 코드도 간결하다.