找到所有m子序列的最大加权和

时间:2012-06-02 10:39:24

标签: c algorithm sum weighted kadanes-algorithm

我试图解决以下问题:

Weighted Sum Problem

我之前遇到的最接近的问题是Kadane的算法,所以我尝试了“max ending here”方法,这导致了以下基于DP的程序。我们的想法是将问题分解为更小的相同问题(通常的DP)。

#include<stdio.h>
#include<stdlib.h>


main(){
int i, n, m, C[20002], max, y, x, best, l, j;
int a[20002], b[20002];
scanf("%d %d", &n, &m);
for(i=0;i<n;i++){
    scanf("%d",&C[i]);
}
a[0] = C[0];
max = C[0];
for(i=1;i<n;i++){
    max = (C[i]>max) ? C[i] : max;
    a[i] = max;
}

for(l=0;l<n;l++){
    b[l] = 0;
}

for(y=2;y<m+1;y++){

    for(x=y-1;x<n;x++){

        best = max = 0;
        for(j=0;j<y;j++){
        max += (j+1) * C[j];
        }

        for(i=y-1;i<x+1;i++){
            best = a[i-1] + y * C[i];
            max = (best>max) ? best : max;
        }
        b[x] = max;
    }

    for(l=0;l<n;l++){
    a[l] = b[l];                 
    }
}
printf("%d\n",b[n-1]);
system("PAUSE");
return 0;
}

但是这个程序在指定的时间限制内不起作用(空间限制很好)。请给我一个关于这个问题的算法的提示。

EDIT。

以下是代码的说明: 就像在Kadane中一样,我的想法是查看特定的C [i],然后对以C [i]结尾的m子序列取最大加权和,最后取所有i的最大值。这将给我们答案。现在请注意,当你查看以C [i]结尾的m子序列并取最大加权和时,这相当于取C [0]中包含的(m-1) - 子序列的最大加权和。到C [i-1]。这是一个较小的问题,与我们原来的问题完全相同。所以我们使用递归。为了避免对函数进行双重调用,我们创建了一个值为f [i] [j]的表,其中f [ii] [j]是问题的答案,这与我们的问题相同,其中n替换为i,m替换为学家也就是说,我们构建了一个f [i] [j]的表,我们的最终答案是f [n-1] [m](也就是说,我们使用memoization)。现在注意到只需要前一列来计算条目f [i] [j],仅保留数组就足够了。那些数组是'a'和'b'。

抱歉,长篇大论,无法帮助它。 :(

2 个答案:

答案 0 :(得分:0)

您的一般方法是正确的。但是你的算法存在问题。

你可以替换内环的主体

    best = max = 0;
    for(j=0;j<y;j++){
    max += (j+1) * C[j];
    }

    for(i=y-1;i<x+1;i++){
        best = a[i-1] + y * C[i];
        max = (best>max) ? best : max;
    }
    b[x] = max;

   b[x] = MAX(b[x-1],a[x-1] + y * C[x]);

这将改善算法的时间复杂度。即避免重新计算b[i] 所有i < x。动态编程的一个共同特征。

答案 1 :(得分:0)

尝试0/1 Knapsack without repetition方法,在每个步骤中我们决定是否包含项目。

MWS(i, j)代表optimal maximum weighted sumC[i...N]i不同的子问题0 <= i <= N的{​​{1}},我们的目标是找出1 <= j <= M的价值。

MWS(i,j)可以用递归方式表示如下。

enter image description here

我将边界条件处理作为练习。

相关问题