作业之间的间隔最小

时间:2017-08-19 13:27:49

标签: algorithm dynamic-programming

我试图解决最小化数组中给出的作业之间的时间间隔总和的问题。工作结构如下:

struct Job{ int start, end; };

,功能原型是:

int impatientBob(Job jobs[], int n, int k)

乔布斯不能重叠,我必须从数组中选择k或者如果不可能则返回-1。此外,数组按作业的结束时间排序,时间以分钟为单位。 我没有任何好主意,因为我对动态编程还很陌生。

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工作。