最大连续和

#include 
#include 
#include 
#include 

using namespace std;

// 直接暴力枚举
void consecutive_sum()
{
    // 每次ij区间数组都重新求和
    // n 500 tot 20958500

    // 数组赋值
    srand(time(NULL));
    int n;
    scanf("%d", &n);
    int A[n];
    for(int i = 0; i < n; i++) A[i] = (rand()%20-10);

    // 求最长和
    int tot = 0;    // 累计加法次数
    int longest = A[0];
    int sum = 0;
    for(int i = 0; i < n; i++)
        for(int j = i; j < n; j++)
        {
            sum = 0;
            for(int k = i; k <= j; k++)
                { sum += A[k]; tot++; }
            if(sum > longest) longest = sum;
        }
    printf("\n%d %d", longest, tot);
}

// 暴力优化
void consecutive_sum1()
{
    // Sij = S[i] - S[j]
    // 事先保存0-i的S就可以不用每次重新求和
    // n 500 tot 125749

    // 数组赋值
    int n;
    scanf("%d", &n);
    int A[n];
    srand(time(NULL));
    for(int i = 0; i < n; i++) { A[i] = rand()%20-10; printf("%d ", A[i]); }

    // sum数组赋值
    int sum[n];
    sum[0] = A[0];
    int tot = 0;        // 累计加法次数
    for(int i = 1; i < n; i++) { sum[i] = sum[i-1] + A[i]; tot++; }

    // 求最长和
    int longest = A[0];
    for(int i = 1; i < n; i++)
        for(int j = i-1; j >= -1; j--)
            { longest = max(longest, sum[i] - ((j == -1) ? 0 : sum[j])); tot++; }
    printf("\n%d %d", longest, tot);

}

// 暴力再优化
void consecutive_sum3()
{
    // 上面虽然优化了枚举,但还是要枚举j(0-i)到i的所有可能连续长度,求其中的最长长度
    // 如果i是固定的,要使S[i]-S[j]最大,上面一种是直接j从i-10枚举
    // 其实可以事先保存S[i]前面的最小连串,就可以使得S[i]-S[j]最大
    int n;
    scanf("%d", &n);
    srand(time(NULL));
    int A[n];
    for(int i = 0; i < n; i++) { A[i] = rand()%20-10; printf("%d ", A[i]); }

    int sum[n];
    sum[0] = A[0];
    for(int i = 1; i < n; i++) sum[i] = sum[i-1] + A[i];

    int smallest[n];
    smallest[0] = A[0];
    for(int i = 1; i < n; i++) smallest[i] = min(smallest[i-1], sum[i]);

    int longest = A[0];
    for(int i = 1; i < n; i++) longest = max(max(longest, sum[i] - smallest[i-1]), sum[i]);

    printf("\n%d", longest);
}



// 分治
// 返回数组闭区间 [x, y] 的最大连续和
// 有人用左闭右开区间 [x, y)
int daq(int *A, int x, int y)
{
    // 一个值时递归结束
    if(x == y) return A[x];

    // 分区间,分别递归求两区间最大连续和
    int m = x + (y-x)/2;
    int llongest = daq(A, x, m);
    int rlongest = daq(A, m+1, y);
    int lrlongest = max(llongest, rlongest);

    // 合并,分别求左右区间最大连续和并相加
    int lclongest = A[m], temp = 0;
    for(int i = m; i >= x; i--) lclongest = max(lclongest, temp += A[i]);   // 赋值运算本身具有返回值
    int rcolongest = A[m+1], temp1 = 0;
    for(int i = m+1; i <= y; i++) rcolongest = max(rcolongest, temp1 += A[i]);

    // 取最大返回
    return max(lrlongest, lclongest+rcolongest);
}

void consecutive_sum2()
{
    int n;
    scanf("%d", &n);
    srand(time(NULL));
    int A[n];
    for(int i = 0; i < n; i++) { A[i] = rand()%20-10; printf("%d ", A[i]); }
    int longest = daq(A, 0, n-1);
    printf("\n%d", longest);
}



int main()
{
    consecutive_sum2();
    return 0;
}

你可能感兴趣的:(ACM_BF,BA_OTH,BA_DP)