ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [그리디] 도서관 (1461)(C++)
    BOJ C++ 알고리즘 공부 2022. 4. 3. 17:04

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

     

    1461번: 도서관

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

    www.acmicpc.net

     

     

    1. 문제 개요

     

    세준이는 도서관에서 일한다. 도서관의 개방시간이 끝나서 세준이는 사람들이 마구 놓은 책을 다시 가져다 놓아야 한다. 세준이는 현재 0에 있고, 사람들이 마구 놓은 책도 전부 0에 있다. 각 책들의 원래 위치가 주어질 때, 책을 모두 제자리에 놔둘 때 드는 최소 걸음 수를 계산하는 프로그램을 작성하시오. 세준이는 한 걸음에 좌표 1칸씩 가며, 책의 원래 위치는 정수 좌표이다. 책을 모두 제자리에 놔둔 후에는 다시 0으로 돌아올 필요는 없다. 그리고 세준이는 한 번에 최대 M권의 책을 들 수 있다.

     

     

    2. 입출력

     

     

    3. 문제 풀이

     

    다음과 같이 세준이가 6개의 책을 정리해야한다고 가정해보자.

    책1,책2,책3은 마이너스 좌표에 있고 책4,책5,책6은 플러스 좌표에 있다.

    세준이는 최대 2개의 들 수 있다.

     

    직관적으로 생각해보면 세준이는 책1, 책6을 정리하기 위해서는 책1,6이 있는 위치에 무조건 가야한다. 그러나 책2,3,4,5는 책1, 책6을 놓으러 다녀오는 길에 정리하고 올 수 있다.

    그렇다면 책을 정리하고 오는 거리를 최소화하는 방법은 무엇일까?

     

    책1을 놓고오는 길에 책3을 놓고오면 세준이가 책1,2,3을 놓고오는 거리는 책1의 거리 + 책2의 거리가 된다. 하지만 책1을 놓고오는 길에 책2를 놓고오면 책1의 거리+책3의 거리가 된다. 후자의 값이 더 작으므로 이와같이 그리디하게 선택해주면 된다.

     

    또한 음수값을 갖는 좌표와 양수값을 갖는 좌표는 어차피 세준이가 책을 가지고 있는 0의 값에 들려야하므로 별개로 생각할 수 있다.

     

    마지막으로 세준이가 0의 좌표값에 돌아오지 않아도 되므로 책1, 책6의 좌표중 거리가 더 먼 좌표를 편도로 다녀오는 것으로 계산해주고 나머지는 왕복으로 계산해주면 된다.

                                                                  

     

    4. 전체 코드

     

    #include<iostream>
    #include<vector>
    #include<algorithm>
    
    using namespace std;
    
    bool compare(int a, int b){
        return a>b;
    }
    
    int main(void)
    {
        int N, M; //책의수, 한번에들수있는수
        int dist = 0;
        vector<int> positiveV,negativeV; //양수, 음수를 나눠서 저장
        
        scanf("%d%d",&N,&M); //도시 개수
        
        int temp;
        for(int i=0;i<N;i++){
            scanf("%d",&temp);
            if(temp<0) negativeV.push_back(temp);
            else positiveV.push_back(temp);
        }
        
        //절댓값이 큰 순으로 정렬
        sort(positiveV.begin(), positiveV.end(),compare);
        sort(negativeV.begin(), negativeV.end());
        
        int i=0;
        while(i<positiveV.size()){
            dist += (2*positiveV[i]); //왕복 거리 계산 
            i += M; //M만큼 스킵
        }
        i=0;
        while(i<negativeV.size()){
            dist -= (2*negativeV[i]); //왕복 거리 계산 
            i += M; //M만큼 스킵
        }
       //벡터 안에 값이 없는 경우에 0번째 주소를 접근하면 안되므로 다음과 같이 대입
        int temp1=(positiveV.size()==0)?0:positiveV[0];
        int temp2=(negativeV.size()==0)?0:-1*negativeV[0];
        
        //양 끝의 최댓값 중 더 큰 값을 편도로 계산하기 위해 한 번 빼준
        dist -= (max(temp1,temp2));
        printf("%d\n",dist);
    }

    댓글

Designed by Tistory.