加权区间调度问题&动态程序

发布于 2024-09-16 02:14:47 字数 3065 浏览 7 评论 0原文

我的问题与 其他讨论有关

我正在尝试使用动态程序将该算法实现为递归调用。

问题陈述:

作业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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你穿错了嫁妆 2024-09-23 02:14:47

让我们考虑一个简单的案例,一项工作。您将调用

long res = computeOpt(njobs-1); // computeOpt(0)

然后,您就拥有了

    if (j == 0)
        return 0;

computeOpt内部。所以,你不能从一份工作中赚到任何钱。

在一般情况下,由于上面的行,您似乎忽略了第一份工作。 if (j < 0) 应该效果更好。

PS 在进入“10k 到 1m 随机生成的作业集”之前,请务必测试简单和琐碎的情况。它们更容易验证和调试。

Let's consider trivial case, one job. You'll call

long res = computeOpt(njobs-1); // computeOpt(0)

Then, you have

    if (j == 0)
        return 0;

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文