【算法竞赛入门经典】8.1 最大连续子序列和

共提供fun1()~fun5()五种方法。
fun1()为暴力
fun2()使用了Sn进行优化,每次计算区间i~j的时候就不需要逐个累加了
fun3()是典型分治法,假设三种情况:起末位置均在mid往左,起末位置均在mid往右,起点在mid往左,终在mid往右。
fun4()是动态规划,使用了状态转移方程sum[i] = max{sum[i-1]+dat[i],dat[i]}
fun5()是fun4()的空间优化版本,不需要开数组了。

#include<iostream>
#include<algorithm>
#include<ctime>
using namespace std;
int dat[10] = { -10,1,2,3,4,-5,-23,3,7,-21 };
int fun1() {//暴力求解
    int maxi = dat[0];
    for (int i = 0; i < 10; i++) {
        for (int j = i; j < 10; j++) {
            int sum = 0;
            for (int k = i; k <= j; k++) {
                sum += dat[k];
            }
            maxi = max(maxi, sum);
        }
    }
    return maxi;
}
int fun2() {//sum和优化
    int sum[11], maxi = dat[0];
    sum[0] = 0;
    for (int i = 1; i <= 10; i++)
        sum[i] = dat[i - 1] + sum[i - 1];
    for (int i = 0; i < 10; i++) {
        for (int j = i + 1; j < 10; j++) {
            int temp = sum[j] - sum[i];
            maxi = max(maxi, temp);
        }
    }
    return maxi;
}
int fun3(int left,int right) {//分治法
    if (right - left == 1)
        return dat[left];
    int Lmax, Rmax, mid, v, sidemax;
    mid = (left + right) / 2;
    sidemax = max(fun3(left, mid), fun3(mid, right));
    v = 0;
    Lmax = dat[mid - 1];
    for (int i = mid - 1; i >= left; i--) {
        v += dat[i];
        Lmax = max(Lmax, v);
    }
    v = 0;
    Rmax = dat[mid];
    for (int i = mid; i < right; i++) {
        v += dat[i];
        Rmax = max(Rmax, v);
    }
    return max(sidemax, Lmax + Rmax);
}
int fun4() {//dp;sum[i] = max{sum[i-1]+dat[i],dat[i]}. (sum[i]记录以a[i]为子序列末端的最大序子列连续和)
    int sum[10], maxi;
    sum[0] = maxi = dat[0];
    for (int i = 1; i < 10; i++) {
        sum[i] = max(sum[i - 1] + dat[i], dat[i]);
        maxi = max(maxi, sum[i]);
    }
    return maxi;
}
int fun5() {//对dp的优化,不需要开数组了
    int maxi, temp;
    maxi = temp = dat[0];
    for (int i = 1; i < 10; i++) {
        if (temp > 0)
            temp += dat[i];
        else
            temp = dat[i];
        if (temp > maxi)
            maxi = temp;
    }
    return maxi;
}
int main() {
    clock_t t1, t2;
    t1 = clock();
    cout << fun1() << endl;
    t2 = clock();
    cout << t2 - t1 << " ms" << endl << endl;

    t1 = clock();
    cout << fun2() << endl;
    t2 = clock();
    cout << t2 - t1 << " ms" << endl << endl;

    t1 = clock();
    cout << fun3(0, 10) << endl;
    t2 = clock();
    cout << t2 - t1 << " ms" << endl << endl;

    t1 = clock();
    cout << fun4() << endl;
    t2 = clock();
    cout << t2 - t1 << " ms" << endl << endl;

    t1 = clock();
    cout << fun5() << endl;
    t2 = clock();
    cout << t2 - t1 << " ms" << endl << endl;

    getchar();
    getchar();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值