加权区间调度问题&动态程序
我的问题与 其他讨论有关。
我正在尝试使用动态程序将该算法实现为递归调用。
问题陈述:
作业j从sj
开始,在fj
结束,并且具有权重或值vj
。
如果两个工作不重叠,则可以兼容。
目标:找到相互兼容的工作的最大权重子集。
书籍提出的解决方案是使用一个解决方案表来存储所有子问题,在递归迭代调用过程中需要时可以重用这些子问题。
解决问题的步骤是:
Input: n, s1,...,sn , f1,...,fn , v1,...,vn
Sort jobs by finish times so that f1 > f2 >... > fn.
Compute p(1), p(2), ..., p(n)
Where p(j) = largest index i < j such that job i is compatible with j.
for j = 1 to n
M[j] = empty <-- solution table
M[j] = 0
M-Compute-Opt(j) {
if (M[j] is empty)
M[j] = max(wj + M-Compute-Opt(p(j)), M-Compute-Opt(j-1))
return M[j]
}
这是我的代码(相关部分):
全局变量:
typedef struct {
long start, stop, weight;
} job;
/* job array */
job *jobs;
/* solutions table */
long *solutions;
/* P(j) */
long *P;
-按完成时间对作业进行排序,以便 f1 > > f2>...> fn
int compare(const void * a, const void * b) {
const job *ad = (job *) a;
const job *bd = (job *) b;
return (ad->stop - bd->stop);
}
//Jobs is filled above by parsing a datafile
qsort(jobs, njobs, sizeof(job), compare);
计算 p(1), p(2), ..., p(n) 其中 p(j) = 最大索引 i < j 使得工作 i 与 j 兼容。
/*bsearch for finding P(J) */
int jobsearch(int start, int high){
if (high == -1) return -1;
int low = 0;
int best = -1;
int mid;
int finish;
while (low <= high){
mid = (low + high) /2 ;
finish = jobs[mid].stop;
if (finish >= start){
high = mid-1;
}else{
best = mid;
low = mid + 1;
}
}
return best;
}
int best;
for (i = 0; i < njobs; i++){
solutions[i] = -1l; //solutions table is initialized as -1
best = jobsearch(jobs[i].start,i-1);
if (best != -1)
P[i] = best;
else
P[i] = 0;
}
M-Compute-Opt(j):
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
/**
* The recursive function with the dynamic programming reduction
*/
long computeOpt(long j) {
if (j == 0)
return 0;
if (solutions[j] != -1l) {
return solutions[j];
}
solutions[j] = MAX(jobs[j].weight + computeOpt(P[j]), computeOpt(j - 1));
return solutions[j];
}
long res = computeOpt(njobs-1);
printf("%ld\n", res);
我针对多个具有大数据(从 10k 到 1m 随机生成的作业集)的测试用例运行我的程序,将我的输出与预期结果进行比较。在某些情况下它会失败。有时我的输出比预期结果大一点,有时又比预期小一点。我显然错过了一些东西。请注意,在大多数情况下,我的输出是正确的,所以我认为有一些特殊情况我无法正确处理,
我无法找出问题所在。
感谢任何帮助
更新: 我将递归函数更改为迭代函数,现在所有测试文件的结果都是正确的。 我再次不明白为什么递归不起作用
My question is related to this other discussion.
I'm trying to implement that algorithm using the dynamic program into a recursive call.
Problem statement:
Job j starts at sj
, finishes at fj
,and has weight or value vj
.
Two jobs compatible if they don't overlap.
Goal: find maximum weight subset of mutually compatible jobs.
The solution proposed by books is to use a solution table to store all suproblems which will be reused when needed during a recursive o iterative call.
The steps to solve the problem are:
Input: n, s1,...,sn , f1,...,fn , v1,...,vn
Sort jobs by finish times so that f1 > f2 >... > fn.
Compute p(1), p(2), ..., p(n)
Where p(j) = largest index i < j such that job i is compatible with j.
for j = 1 to n
M[j] = empty <-- solution table
M[j] = 0
M-Compute-Opt(j) {
if (M[j] is empty)
M[j] = max(wj + M-Compute-Opt(p(j)), M-Compute-Opt(j-1))
return M[j]
}
And this is my code (the relevant parts):
global vars:
typedef struct {
long start, stop, weight;
} job;
/* job array */
job *jobs;
/* solutions table */
long *solutions;
/* P(j) */
long *P;
-Sort jobs by finish times so that f1 > f2 >... > fn
int compare(const void * a, const void * b) {
const job *ad = (job *) a;
const job *bd = (job *) b;
return (ad->stop - bd->stop);
}
//Jobs is filled above by parsing a datafile
qsort(jobs, njobs, sizeof(job), compare);
Compute p(1), p(2), ..., p(n)
Where p(j) = largest index i < j such that job i is compatible with j.
/*bsearch for finding P(J) */
int jobsearch(int start, int high){
if (high == -1) return -1;
int low = 0;
int best = -1;
int mid;
int finish;
while (low <= high){
mid = (low + high) /2 ;
finish = jobs[mid].stop;
if (finish >= start){
high = mid-1;
}else{
best = mid;
low = mid + 1;
}
}
return best;
}
int best;
for (i = 0; i < njobs; i++){
solutions[i] = -1l; //solutions table is initialized as -1
best = jobsearch(jobs[i].start,i-1);
if (best != -1)
P[i] = best;
else
P[i] = 0;
}
M-Compute-Opt(j):
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
/**
* The recursive function with the dynamic programming reduction
*/
long computeOpt(long j) {
if (j == 0)
return 0;
if (solutions[j] != -1l) {
return solutions[j];
}
solutions[j] = MAX(jobs[j].weight + computeOpt(P[j]), computeOpt(j - 1));
return solutions[j];
}
long res = computeOpt(njobs-1);
printf("%ld\n", res);
I run my program against several test cases with large data (from 10k to 1m random generated jobs set) comparing my output to the expected result. In some cases it fails. Sometime my output is e bit greater and sometime is a bit lesser than the expected result. I'm missing somethings obviously. Note that in the most of the cases my output is correct so I think there is some specials condition I can't handle properly
I cant't find out where the problem is.
Any help is appreciated
UPDATE:
I changed the recursive function into an iterative one and now the result is correct for all test file.
Again I can't understand why the recursive one not works
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
让我们考虑一个简单的案例,一项工作。您将调用
然后,您就拥有了
computeOpt
内部。所以,你不能从一份工作中赚到任何钱。在一般情况下,由于上面的行,您似乎忽略了第一份工作。
if (j < 0)
应该效果更好。PS 在进入“10k 到 1m 随机生成的作业集”之前,请务必测试简单和琐碎的情况。它们更容易验证和调试。
Let's consider trivial case, one job. You'll call
Then, you have
inside
computeOpt
. So, you can't earn anything from one job.In general case, you seem to ignore first job due to the line above.
if (j < 0)
should work better.PS Always test simple and trivial cases before you go to "10k to 1m random generated jobs set". They are easier to verify and easier to debug.