0

N 個の整数の配列が与えられます。
配列の最大合計は、この配列の空でない連続する部分配列の要素の最大合計です。
たとえば、配列 [1, -2, 3, -2, 5] の最大合計は 6 です。これは、部分配列 [3, -2, 5] の合計が 6 であり、それ以上の部分配列合計を達成することが不可能であるためです。
これで、指定された配列から要素を 1 つしか削除できなくなりました。そうすることで達成できる結果の配列の最大可能最大合計はいくらですか?

私は自分のテストケースで自分のコードをテストしています。dev-c++ で正しい出力が得られます。しかし、コードをオンラインでテストすると、間違った答えが返ってきます。何が問題なのかわかりません。

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
struct result{
    long long int start;
    long long int end;
    long long int sum;
}res;
long long int find_max(long long int a[],long long int n)
{
    long long int max=LLONG_MIN;
    long long int i;
    for(i=0;i<n;++i)
    {
        if(a[i]>max)
            max=a[i];
    }
    return max;
}
long long int max_sub(long long int a[],long long int n)
{
    long long int i;
    long long int min,sum1=0;
    struct result max,max_curr,*maxsub;
    maxsub=calloc(sizeof(res),n);
    max.sum=LLONG_MIN;
    max_curr=max;
    for(i=0;i<n;++i)
    {
        if(max_curr.sum<0)
        {
            max_curr.sum=a[i];
            max_curr.start=i;
            max_curr.end=i;
        }
        else
        {
            max_curr.sum+=a[i];
            max_curr.end=i;
        }
        if(max_curr.sum>max.sum)
        {
            max=max_curr;
        }
        maxsub[i]=max;
    }
    min=0;
    for(i=maxsub[n-1].start;i<=maxsub[n-1].end;++i)
    {
        if(a[i]<0)
        {
            if(min==0 || a[i]<min)
                min=a[i];
        }
    }
    sum1=maxsub[n-1].sum-min;
    return sum1;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        long long int n,i;
        scanf("%lld",&n);
        long long int a[n];
        for(i=0;i<n;++i)
            scanf("%lld",&a[i]);
        long long int sum=0;
        sum=find_max(a,n);
        if(sum<=0)
        {
            printf("%lld\n",sum);
        }
        else
        {
            sum=max_sub(a,n);
            printf("%lld\n",sum);
        }

    }
    return 0;
}
4

6 に答える 6

4

まあ、これは公平ではありません。人々は懸命に解読に取り組んできました。これは code-chef で進行中のオンライン コンテストの一部です。このスレッドを閉じてください。

EDIT : コンテストは終了しました。議論の余地を残してください :)

于 2016-05-31T10:11:26.943 に答える
0

明らかに、配列内のサブ配列の最大和を見つけるために Kadane のアルゴリズムを実装しました。与えられた配列は: [1, -2, 3, -2, 5]
Kadane の結果: [3, -2 ,5 ]

今あなたがしていることは、部分配列の最小要素を削除することですが、これは残念ながら正しくありません。
与えられた配列は次のとおりです: [1, -2, 3, -2, 5, -33, 5]
Kadane の結果: [3, -2 ,5]
あなたの出力: [3, 5] , すなわち 8

しかし、ここでの正しい答えは、部分配列 [3, -2, 5, -33, 5] を選択し、'-33' を削除することであり、出力は 11. (3+5+5-2) になります。

ありがとう。
PS: stackoverflow に関する私の最初の回答です。これは私が説明した 1 つの例外に過ぎず、他にもたくさんあります。
幸運を!

于 2016-05-29T09:22:43.767 に答える
-1
#include<stdio.h>
#include<limits.h>
long long int sum;
long long int rightsum(long long int a[], long  int n, long int start, long int end) {

    long int i;
    long long int max_so_far=INT_MIN,max_ending_here=0;
    for(i=start;i<=end;i++)
    {
       max_ending_here = max_ending_here + a[i];
        if (max_so_far < max_ending_here)
        {
            max_so_far = max_ending_here;
        }  
    }
    return max_so_far;
}
long long int leftsum(long long int a[], long long int n, long long int start, long long int end) {

    long int i;
    long long int max_so_far=INT_MIN,max_ending_here=0;
    for(i=end;i>=start;i--)
    {
      max_ending_here = max_ending_here + a[i];
        if (max_so_far < max_ending_here)
        {
            max_so_far = max_ending_here;
        }  
    }
    return max_so_far;
}
long long int maxSum(long long int a[],long int n) {

    long long int sum = rightsum(a, n, 1, n - 1);
    long int i;

    for (i = 0; i < n; i ++) {

        long long int l = leftsum(a, n, 0, i - 1);
        long long int r = rightsum(a, n, i + 1, n - 1);


        if (((i > 0) && (i < n - 1)) && ( l>=0) && (r>0) && (l+r>sum)) {

            sum = l+r;
            if(sum<sum+a[i])
            {
                sum=sum+a[i];
            }

        }


        else if ((i > 0) && (l >= r) && (l>sum)) {
            sum = l;

            if(sum<sum+a[i])
            {
                sum=sum+a[i];
            }

        }

        else if ((i < n - 1) ) {
            sum = r;

            if(sum<sum+a[i])
            {
                sum=sum+a[i];
            }

        }
    }
    return sum;
}
int main()
{
    int t;
    long long i,n;
    long long int a[100000];
    scanf("%d",&t);
    while(t!=0)
    {
        scanf("%ld",&n);
        for(i=0;i<n;i++)
        {
            scanf("%lld",&a[i]);
        }
        printf("%lld\n",maxSum(a,n));
        t--;
    }
    return 0;
} 
于 2016-05-29T12:39:59.360 に答える
-1

結果から最小数を引く理由:

/*min=0;
for(i=maxsub[n-1].start;i<=maxsub[n-1].end;++i)
{
    if(a[i]<0)
    {
        if(min==0 || a[i]<min)
            min=a[i];
    }
}*/
sum1=maxsub[n-1].sum;//-min;
return sum1; // Works fine
于 2016-05-28T12:11:41.487 に答える