Минимальные интервалы между заданиями
Я пытаюсь решить проблему минимизации суммы временных интервалов между заданиями, заданными в массиве. Структура задания следующая:
struct Job{ int start, end; };
и прототипом функции является:
int impatientBob(Job jobs[], int n, int k)
Задания не могут пересекаться, и я должен выбрать k из них из массива или вернуть -1, если это невозможно. Кроме того, массив сортируется по времени окончания заданий, а время указывается в минутах. У меня нет никакой хорошей идеи, потому что я до сих пор совершенно новичок в динамическом программировании.
Одно из решений, о котором я могу думать, - со сложностью O(n^2 * k)
.
Вы можете сделать что-то подобное (следующее просто псевдокод):
int minTimeIntervals(current_index, last_taken, k){
if(k == 0) return 0 // if you already taken k jobs then you're done
if(current_index == n) return BIG NUMBER // if you reached the end of the jobs without taking k jobs, then this is an invalid solution. Set it to a big number so when you minimize it always neglected.
check if the given state is memorized and has been calculated before.
decision1 = minTimeIntervals(current_index + 1, last_taken, k) // Choose not to take the current job and move to the next.
if(start time of current job > end time of last taken job){
// Choose to take the current job of that valid (i.e they don't intersect)
decision2 = minTimeIntervals(current_index + 1, current_index, k-1) + difference of time between last_taken and current_index
}
return minimum of decision1 and decision2 and memorize the answer for the given state.
}
EDIT: добавление более конкретного кода.
int memo[N][N][K]; // Should be initialized with -1
int minTimeIntervals(int current_index, int last_taken, int k){
if(k == 0) return 0;
if(current_index == N) return 1<<27; // 2^27, Just a big number.
if(last_taken != -1 && memo[current_index][last_taken][k] != -1) return memo[current_index][last_taken][k];
int decision1 = minTimeIntervals(current_index + 1, last_taken, k);
int decision2 = 1<<27;
if(last_taken == -1 || jobs[current_index].start >= jobs[last_taken].end){
decision2 = minTimeIntervals(current_index + 1, current_index, k - 1) + (jobs[current_index].start - jobs[last_taken].end);
}
int result = min(decision1, decision2);
memo[current_index][last_taken][k] = result;
return result;
}
Что делает этот код, так это то, что для данного состояния (current_index, last_taken, k)
он вычисляет ответ и сохраняет его в memo[current_index][last_taken][k]
.
Память массива должна быть инициализирована некоторым значением, которое никогда не может быть допустимым ответом (например, -1). Теперь, если значение memo[i][j][k]
- -1, это означает, что мы раньше не вычисляли состояние (i, j, k), поэтому мы вычислим его и сохраним в memo[i][j][k]
.
Если для некоторого заданного состояния (i, j, k) значение в memo[i][j][k]
было некоторым неотрицательным значением (скажем, 5), это означает, что мы обработали это состояние раньше и ответ был равен 5, поэтому просто верните этот ответ, не повторяя вычисления.
Последняя сложная часть состоит в том, что когда вы выбираете свою первую работу, у вас нет предыдущей работы, чтобы рассчитать разницу во времени. Для этого мы устанавливаем last_taken как -1, поэтому мы знаем, что это первое задание, и нам не нужно вычислять разницу во времени между current_index и last_taken.
Теперь ваша основная функция impatientBob
должна выполнить некоторую работу по инициализации, например, установить значения memo
на -1, затем вызвать функцию minTimeIntervals(0, -1, k)
что означает, что вы начинаете с первого задания, которое вы не сделали любые предыдущие задания раньше, и вам все равно нужно выполнить k заданий.
- Вопросы
- Dynamic-programming
- Минимальные интервалы между заданиями