알고리즘/문제 풀이

1461번: 도서관

Themion 2021. 12. 8. 12:18

https://www.acmicpc.net/problem/1461

 

1461번: 도서관

세준이는 도서관에서 일한다. 도서관의 개방시간이 끝나서 세준이는 사람들이 마구 놓은 책을 다시 가져다 놓아야 한다. 세준이는 현재 0에 있고, 사람들이 마구 놓은 책도 전부 0에 있다. 각 책

www.acmicpc.net

원위치를 부호에 따라 나누어 저장한 뒤 정렬하는 문제이다. M개 이하의 책을 모두 가져다 놓고 올 때 최소 걸음 수는 (원위치의 절댓값의 최댓값) * 2이고, 마지막 책더미를 가져다 놓은 뒤에는 돌아올 필요가 없음에 유의하자.

#include <algorithm>
#include <cstdio>
#include <vector>

using namespace std;

int main() {
    // N: 책의 수, M: 한번에 옮길 수 있는 책의 수
    // ans: 최소 걸음의 수
    int N, M, ans = 0;
    // p, n: 각각 양수, 음수 위치에 가져다 두어야 할 책의 원위치의 집합
    vector<int> p, n;

    scanf("%d %d", &N, &M);
    // 모든 책에 대해
    while (N--) {
        // 책의 원위치를 입력받은 뒤
        scanf("%d", &ans);
        // 위치가 양수라면 p에, 음수라면 n에 push
        (ans > 0 ? p : n).push_back(ans);
    }

    // 빈 배열이 존재하면 에러가 발생하므로 빈 값을 push
    if (p.empty()) p.push_back(0);
    if (n.empty()) n.push_back(0);

    // 처음 위치로부터 거리가 먼 순으로 정렬
    sort(p.begin(), p.end(), [](int a, int b) { return a > b; });
    sort(n.begin(), n.end(), [](int a, int b) { return a < b; });

    // 초기 상태에서 걸음의 수는 0
    ans = 0;
    // 거리가 먼 순으로 M개의 책을 차례로 가져다 놓고 돌아온다
    for (int i = 0; i < p.size(); i += M) ans += 2 * p[i];
    for (int i = 0; i < n.size(); i += M) ans -= 2 * n[i];

    // 거리가 가장 먼 곳은 책을 가져다 둔 뒤 돌아올 필요가 없으므로
    // 해당 거리만큼 ans에서 빼 준다
    ans -= p[0] > -n[0] ? p[0] : -n[0];

    // 정답을 출력
    printf("%d\n", ans);

    return 0;
}

'알고리즘 > 문제 풀이' 카테고리의 다른 글

1475번: 방 번호  (0) 2021.12.08
1463번: 1로 만들기  (0) 2021.12.08
1436번: 영화감독 숌  (0) 2021.12.08
1427번: 소트인사이드  (0) 2021.12.08
1421번: 나무꾼 이다솜  (0) 2021.12.08