其他分享
首页 > 其他分享> > 动态规划 最大子段和

动态规划 最大子段和

作者:互联网


代码来源于《计算机算法设计与分析》-王晓东,我只是整理一下代码笔记方便复习


<1> 蛮力法

代码;

/******************************************
 * @Author       : 鱼香肉丝没有鱼
 * @Date         : 2021-09-20 12:55:54
 * @LastEditors  : 鱼香肉丝没有鱼
 * @LastEditTime : 2021-11-24 01:29:41
 ******************************************/

// 矩阵连乘
#include <iostream>
#include <stdio.h>

using namespace std;

// 蛮力法遍历每一种组合
int MaxSum(int n, int* a, int& besti, int& bestj)
{
    int sum = 0;
    for(int i = 1; i <= n; i++) {
        for(int j = i; j <= n; j++) {
            int thissum = 0;
            for(int k = i; k <= j; k++) {
                thissum += a[k];
            }
            if(thissum > sum) {
                sum = thissum;
                besti = i;
                bestj = j;
            }
        }
    }
    return sum;
}

int main()
{
    int maxsum = 0;
    int besti = -1;
    int bestj = -1;

    freopen("file out.txt", "r", stdin);
    int n;  //矩阵个数

    cin >> n;
    int* a = NULL;
    a = new int[n + 1];
    for(register int i = 1; i <= n; i++)  // arr的0号位不使用
        cin >> a[i];

    maxsum = MaxSum(n, a, besti, bestj);

    cout << "最大子段和为:" << maxsum << endl;

    return 0;
}

// 6
// -2 11 -4 13 -5 -2

时间复杂度 O(n3)

改进:
去掉其中一个循环

/******************************************
 * @Author       : 鱼香肉丝没有鱼
 * @Date         : 2021-09-20 12:55:54
 * @LastEditors  : 鱼香肉丝没有鱼
 * @LastEditTime : 2021-11-24 01:29:41
 ******************************************/

// 矩阵连乘
#include <iostream>
#include <stdio.h>

using namespace std;

// 蛮力法遍历每一种组合
int MaxSum(int n, int* a, int& besti, int& bestj)
{
    int sum = 0;
    for(int i = 1; i <= n; i++) {
        int thissum = 0;
        for(int j = i; j <= n; j++) {
            thissum += a[j];

            if(thissum > sum) {
                sum = thissum;
                besti = i;
                bestj = j;
            }
        }
    }
    return sum;
}

int main()
{
    int maxsum = 0;
    int besti = -1;
    int bestj = -1;

    freopen("file out.txt", "r", stdin);
    int n;  //矩阵个数

    cin >> n;
    int* a = NULL;
    a = new int[n + 1];
    for(register int i = 1; i <= n; i++)  // arr的0号位不使用
        cin >> a[i];

    maxsum = MaxSum(n, a, besti, bestj);

    cout << "最大子段和为:" << maxsum << endl;

    return 0;
}

// 6
// -2 11 -4 13 -5 -2

时间复杂度 :O(n2)

<2> 分治法

基本思想:
在这里插入图片描述
代码:

/******************************************
 * @Author       : 鱼香肉丝没有鱼
 * @Date         : 2021-09-20 12:55:54
 * @LastEditors  : 鱼香肉丝没有鱼
 * @LastEditTime : 2021-11-24 01:29:41
 ******************************************/

// 矩阵连乘
#include <iostream>
#include <stdio.h>

using namespace std;

int MaxSubSum(int* a, int left, int right)
{
    int sum = 0;
    if(left == right) {  //如果是负数的我们规定负数的和是0
        sum = a[left] > 0 ? a[left] : 0;
    }
    else {
        // 从中间分成两个子串
        int center = (left + right) / 2;
        int leftsum = MaxSubSum(a, left, center);
        int rightsum = MaxSubSum(a, center + 1, right);

        // 左边子串的和
        int s1 = 0;
        int lefts = 0;
        for(int i = center; i >= left; i--) {
            lefts += a[i];
            if(lefts > s1)
                s1 = lefts;
        }

        // 右边子串的和
        int s2 = 0;
        int rights = 0;
        for(int i = center + 1; i <= right; i++) {
            rights += a[i];
            if(rights > s2)
                s2 = rights;
        }

        // 左右两个子串的和的和
        sum = s1 + s2;
        if(sum < leftsum)  //取最大的
            sum = leftsum;
        if(sum < rightsum)
            sum = rightsum;
    }
    return sum;
}

int MaxSum(int n, int* a)
{
    return MaxSubSum(a, 1, n);
}

int main()
{
    int maxsum = 0;

    freopen("file out.txt", "r", stdin);
    int n;  //矩阵个数

    cin >> n;
    int* a = NULL;
    a = new int[n + 1];
    for(register int i = 1; i <= n; i++)  // arr的0号位不使用
        cin >> a[i];

    maxsum = MaxSum(n, a);

    cout << "最大子段和为:" << maxsum << endl;

    return 0;
}

// 6
// -2 11 -4 13 -5 -2

时间复杂度: O(nlogn)

<3> 动态规划

代码:

/******************************************
 * @Author       : 鱼香肉丝没有鱼
 * @Date         : 2021-09-20 12:55:54
 * @LastEditors  : 鱼香肉丝没有鱼
 * @LastEditTime : 2021-11-24 01:29:41
 ******************************************/

// 矩阵连乘
#include <iostream>
#include <stdio.h>

using namespace std;

int MaxSum(int n, int* a)
{
    int sum = 0;
    int b = 0;
    for(int i = 1; i <= n; i++) {
        if(b > 0)
            b += a[i];
        else
            b = a[i];

        if(b > sum)
            sum = b;
    }
    return sum;
}

int main()
{
    int maxsum = 0;

    freopen("file out.txt", "r", stdin);
    int n;  //矩阵个数

    cin >> n;
    int* a = NULL;
    a = new int[n + 1];
    for(register int i = 1; i <= n; i++)  // arr的0号位不使用
        cin >> a[i];

    maxsum = MaxSum(n, a);

    cout << "最大子段和为:" << maxsum << endl;

    return 0;
}

// 6
// -2 11 -4 13 -5 -2

标签:bestj,besti,include,子段,int,sum,鱼香肉丝,动态,规划
来源: https://blog.csdn.net/qq_41680771/article/details/121690675