8

私はこの質問に出くわしました。正の値のみを含む配列がある場合、k個を超える選択された要素のグループが隣接していないという制約の下で、選択された要素の合計を最大化する必要があります。たとえば、入力が1 2 3 1 7 9(n=6およびk=2)の場合。出力は21になります。これは、要素を選択することで得られます_ 2 3 _79.私の単純なDPソリューションはこれです

#include<stdio.h>
#include<limits.h>
#include<malloc.h>


long maxsum(int n,int k,long *sums){
    long *maxsums;
    maxsums = malloc(sizeof(long)*n);
    int i;
    long add  = 0;
    for(i=n-1;i>=n-k;i--){
        add += sums[i];
        maxsums[i] = add;
    }

    for(i = n-k-1;i>=0;i--){
        int j;
        long sum =0,max = 0,cur;
        for(j=0;j<=k;j++){
            cur = sum;
            if((i+j+1)<n)
                cur += maxsums[i+j+1];  
            if(cur > max) max = cur;
            sum += sums[i+j];
        }
        maxsums[i] = max;
    }
    return maxsums[0];
}

int main(){
    int cases=0,casedone=0;
    int  n,k;
    long *array;
    long maxsum = 0;
    fscanf(stdin,"%d %d",&n,&k);
    array = malloc(sizeof(long)*n);
    int i =0;
      while(casedone < n){
            fscanf(stdin,"%ld",&array[casedone]);
        casedone++;
      }
    printf("%ld",maxsum(n,k,array));
}

しかし、これが効率的な解決策であるかどうかはわかりません。複雑さをさらに軽減できますか?ご協力いただきありがとうございます

4

2 に答える 2

0

私はこれがうまくいくと思います:

findMaxSum(int a[], int in, int last, int k) { // in is current index, last is index of last chosen element
    if ( in == size of a[] ) return 0;
    dontChoseCurrent = findMaxSum(a, in+1, last, k); // If current element is negative, this will give better result
    if (last == in-1 and k > 0) { // last and in are adjacent, to chose this k must be greater than 0
        choseCurrentAdjacent = findMaxSum(a, in+1, in, k-1) + a[in];
    }
    if (last != in-1) { // last and in are not adjacent, you can chose this.
        choseCurrentNotAdjacent = findMaxSum(a, in+1, in, k) + a[in];
    }
    return max of dontChoseCurrent, choseCurrentAdjacent, choseCurrentNotAdjacent
}
于 2012-04-06T17:52:07.103 に答える