最大总和(动态规划)

问题描述

大意:

       给定一个序列a[1],a[2],a[3]…a[n],你需要算出其子序列中的最大值。比如说:给你一个序列(6,-1,5,4,-7),它的子序列之和中的最大值是6 + (-1) + 5 + 4 = 14。

输入

大意:

       第一行是一个范围在1到20的整数T,代表着接下来输入的测试案例;

       接下来的T行,每一行都首先是一个范围在1到100000的数字N,代表着该测试案例中所包含的测试数据个数。其次,接着就是N个范围在-1000到1000的测试数据。

输出

大意:

       对于每一个测试案例结果,输出两行。

       第一行是 “Case #:”,#代表着测试案例的序号;

       第二行是三个数据,分别是最大子序列之和、子序列在原序列中的起始位下标加一和末位下标加一;

       如果测试案例不止一个,输出测试案例结果之间需要有一个空行。

算法思想:

       这道题用到的算法思想是动态规划,鉴于该题是入门级的动态规划题,我就简单讲一下我对动态规划的基础认识。

       比如说,1+1+1+1+1=5,那么再加1呢,等于6。可以发现,我们非常快地得出了答案,那是因为我们记住了上一个结果是5,5+1=6。如果我们重新1+1+1+1+1+1=6,那么肯定会慢,而且会造成许多不必要的浪费。

       于是为了解决冗余,我们把从一开始逐步得出的结果记录下来,直到最终得到答案。所以总的来说,这是一个牺牲空间换取时间的算法

解题思路:

       在输入数据同时,数据加到序列和里,边加边比较。最大值小于序列和时,最大值更新,记录起始位,末位数更新为现位。若序列和小于0时,序列和置0,起始位更新为下一位。

#include<iostream>
using namespace std;
int a[100000];
void solve(int k, int n, int t)//动态规划
{
    int sum = 0, max_num = -1000, end_tag, start_tag = 1, temp = 1;//因为所有整数都在-1000到1000之间,所以max_num最小值为-1000
    for (int i = 0; i < n; i++)
    {
        sum += a[i];
        if (sum > max_num)//后面的和>前面的和的情况
        {
            max_num = sum;
            start_tag = temp;//这里是子序列的开始,需要变换,与i无关
            end_tag = i + 1;//这里是子序列的结束,无需变换,只与i有关
        }
        if (sum < 0)//这个地方是最为关键的地方
        {
            temp = i + 2;//序列和置0,起始位更新为下一位。
            sum = 0;
        }
    }
    cout << "Case " << k << ":" << endl;
    if (k != t)
        cout << max_num << " " << start_tag << " " << end_tag << endl << endl;
    else
        cout << max_num << " " << start_tag << " " << end_tag << endl;
}
int main()
{
    int t, n;
    cin >> t;
    for (int i = 1; i <= t; i++)
    {
        cin >> n;//这个是自己错的地方,以为这里也是数列的一部分
        for (int j = 0; j < n; j++)
            cin >> a[j];
        solve(i, n, t);
    }
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值