我试图解决最小化数组中给出的作业之间的时间间隔总和的问题。工作结构如下:
struct Job{ int start, end; };
,功能原型是:
int impatientBob(Job jobs[], int n, int k)
乔布斯不能重叠,我必须从数组中选择k或者如果不可能则返回-1。此外,数组按作业的结束时间排序,时间以分钟为单位。 我没有任何好主意,因为我对动态编程还很陌生。
答案 0 :(得分:0)
我能想到的一个解决方案是复杂度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's 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's 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.
}
编辑:添加更具体的代码。
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工作。