-
[그리디] 도서관 (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); }
'BOJ C++ 알고리즘 공부' 카테고리의 다른 글
[그리디] 잃어버린 괄호(15410)(C++) (0) 2022.04.17 [그리디] 주유소 (13305)(C++) (0) 2022.04.03 [수학] 소수(2581), 약수 구하기(2501) (0) 2022.03.27 [수학] 카잉 달력(6064) (C++) (0) 2022.03.20 [플로이드-와샬] 케빈 베이컨의 6단계 법칙(1389) (C++) (0) 2022.02.27