모든 문제는 C++로 구현되어 있습니다.
이 문제를 풀기 위해, 각 음식을 다 먹는 시간을 기준으로 구간을 나눠볼 수 있다. 아래와 같은 food_times 배열이 주어졌다고 가정해보자.
[10, 15, 4, 7]
가장 먼저 다 먹게되는 음식은 세 번째 음식으로, 다 먹는데에 4 X 4 = 16초가 걸린다.
두번째로 다 먹게 되는 음식은 네 번째 음식으로, 다 먹는데에 16 + (7-4) X 3 = 25초가 걸린다.
세번째로 다 먹게 되는 음식은 첫 번째 음식으로, 다 먹는데에 25 + (10-7) X 2 = 31초가 걸린다.
마지막으로 남는 음식은 두 번째 음식으로, 다 먹는데에 31 + (15-10) X 1 = 36초가 걸린다.
이런 식으로 구간을 나누면 K초 시점에서 몇개의 음식이 남았는지 확인할 수 있다. 그러면 K초에서 바로 이전의 음식을 다먹은 시점의 시간을 뺀 뒤, 이를 남은 음식의 갯수로 나눴을 때 나머지를 구하면 K초 시점에서 먹은 음식의 번호를 알 수 있다. 구간을 구하기 위해서는 새로운 배열을 생성해 내용을 복사한 뒤, 한 번 정렬해서 계산을 수행해야 한다. 계산식은 다음과 같다.
// border : 구간값을 저장하는 배열
// foodNum : food_times 배열의 길이
// tmp : food_times를 복사한 배열
for (i = 1; i < tmp.size(); i++) {
border.push_back(border[i - 1] + (foodNum - i) * (tmp[i] - tmp[i - 1]));
}
이 번호는 이미 다 먹은 음식의 번호를 고려하지 않고 매긴 번호이므로, 다시 food_times 배열을 순회하며 K초 시점에서 다 먹는데 걸리는 시간이 테이블 회전 수보다 작은 음식을 빼고 번호를 다시 매겨줘야 한다.
말로 설명하면 이해하기 어려울 수 있으니, 예시를 들어 확인해보자.

나누는 수에서 1을 빼준 것은 그대로 계산할 경우 첫 번째 음식의 나머지가 1이고 마지막 음식의 나머지가 0이 되므로, 1을 빼줘서 첫번째 음식의 나머지가 0, 마지막 음식의 나머지가 n-1이 되도록 했다.
번호를 구한 뒤에는 다음에 먹어야할 음식을 구하기 위해 구한 번호에 1을 더한 뒤, 남은 음식의 수로 나눈 나머지를 구해준다. 이 값을 food_times를 순회하며 1씩 빼준다. 이때, food_times의 원소가 K초 시점에서 테이블이 회전한 횟수 이하라면 빼지 않고 그냥 넘어간다. 0이 되는 시점의 배열 인덱스가 우리가 최종적으로 구해야 할 음식의 번호이다.
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll; //2019 KAKAO BLIND RECRUITMENT - 무지의 먹방 라이브
int solution(vector<int> food_times, ll k) {
int answer = 0;
ll sum = 0;
for (auto time : food_times) {
sum += time;
}
if (sum <= k) answer = -1;
else {
int i, foodNum = food_times.size();
//1. 각각의 음식을 다 먹는데 걸리는 시간을 차례대로 기록함.
vector<ll> border;
vector<int> tmp = food_times;
sort(tmp.begin(), tmp.end());
border.push_back(foodNum * tmp[0]);
for (i = 1; i < tmp.size(); i++) {
border.push_back(border[i - 1] + (foodNum - i) * (tmp[i] - tmp[i - 1]));
}
//2. k초 동안 먹고 남아있는 음식 수, 테이블 회전 수, 그리고 찾는 음식의 번호를 구한다.
// 여기서 구한 번호는 다 먹은 음식을 생각하지 않고 매긴것이므로, 다시 food_items 배열을 순회하며
// 테이블 회전 수 이하인 음식들을 걸러내고 번호를 다시 매기면 최종 답을 구할 수 있다.
ll rotateNum = 0, eatenFoodNum = 0, last = 0, findNum = -1;
for (i = 0; i < border.size(); i++) {
if (k > border[i]) {
eatenFoodNum++;
last = border[i];
rotateNum = tmp[i];
}
else break;
}
ll div = (foodNum - eatenFoodNum);
findNum = (k - last - 1) % div;
findNum = (findNum + 1) % div;
//3. 다 먹은 음식들은 걸러내고 다시 번호를 매겨 최종 답을 찾는다.
for (i = 0; i < food_times.size(); i++) {
if (food_times[i] <= rotateNum) continue;
if (findNum == 0) {
answer = i + 1;
break;
}
findNum--;
}
}
return answer;
}
'알고리즘 > 프로그래머스' 카테고리의 다른 글
2021 KAKAO BLIND RECRUITMENT - 광고 삽입 (0) | 2021.02.16 |
---|---|
2021 KAKAO BLIND RECRUITMENT - 합승 택시 요금 (0) | 2021.02.16 |
2019 KAKAO BLIND RECRUITMENT - 매칭 점수 (0) | 2021.01.13 |
2019 KAKAO BLIND RECRUITMENT - 오픈채팅방 (0) | 2021.01.12 |