首页 > 其他分享 >使用动态规划法求最大连续子序列和

使用动态规划法求最大连续子序列和

时间:2024-06-01 18:59:37浏览次数:14  
标签:11 arr 规划法 13 数组 序列 动态 dp

通过动态规划方法求最大连续子序列和

问题描述:

给定一个有n(n >= 1)个整数的序列,求出其中最大连续子序列的和。如:{-2, 11, -4, 13, -5, -2},最大的连续子序列是:{11, -4, 13}和为20

【规定】一个序列的最大连续子序列和至少是0,如果小于0,其结果为0。

解法:

使用一个整型数组arr[]来存储序列,即int arr[] = {0, -2, 11, -4, 13, -5, -2},为了处理方便,其中0号下标不用,从1开始处理。

使用一个动态规划数组dp[i]存储以第i个为结束位置的子序列和。并给初值:dp[0] = 0dp[i]dp[i - 1] 的关系为:

dp[i] < 0,按照约定,赋值为0,若dp[i] > 0 则继续累加,即 dp[i] = dp[i - 1] + arr[i]

dp[i] = dp[i - 1] + arr[i];
if (dp[i] < 0)
{
    dp[i] = 0;
}

按照上述,推导序列 {-2, 11, -4, 13, -5, -2}

dp[0] = 0, dp[1] = dp[0] + arr[1] == -2, 因为dp[1] < 0, 则dp[1] = 0

dp[1] = 0, dp[2] = dp[1] + arr[2] == 11, 因为 dp[2] > 0, 则不做处理

dp[2] = 11, dp[3] = dp[2] + arr[3] == 7, 因为dp[3] > 0, 不做处理

dp[3] = 7, dp[4] = dp[3] + arr[4] == 20, 因为dp[4] > 0, 不做处理

dp[4] = 20, dp[5] = dp[4] + arr[5] == 15

dp[5] = 15, dp[6] = dp[5] + arr[6] == 13

dp[6] = 13, 到达数组结尾, 结束遍历.

既得动态规划数组 dp[i]{0, 0, 11, 7, 20, 15, 13}

这一部分的代码实现如下:

dp[0] = 0;
for (int i = 0; i < SIZE; i++)
{
    //求dp[]数组第i个元素的值
    dp[i] = dp[i - 1] + arr[i];
    //如果dp[i]的值小于0,则置0,从第i+1个再重新选
    if (dp[i] <= 0)
    {
        dp[i] = 0;
    }
}

得到了dp[]数组, 那么只要通过遍历它就可以得到最大子序列的和.

//找到最大值的下标
int end = 0;
for (int i = 0; i < SIZE; i++)
{
    if (dp[end] < dp[i])
    {
        end = i;
    }
}

其中end为最大连续子序列的结束位置, 在本例中为4

现在, 还剩下最后一个问题: 怎么推导出最大连续子序列是由哪几个元素组成的?

其实只需要从end 向前遍历到第一个dp[i] == 0的位置就可以确定该子序列是从i + 1的位置开始的.

因为dp[i] != 0dp[i] - dp[i - 1] == arr[i], 则:

dp[4] - dp[3] = a[4] = 13
dp[3] - dp[2] = a[3] = -4
dp[2] - dp[1] = a[2] = 11
dp[1] - dp[0] = a[1] = 0 == dp[1]

因为dp[i] < 0 的时候, 会把dp[i]置为0, 而对于dp[i] > 0 时不会做这个操作, 所以从后向前遍历, 找到第一个为0的元素 i, 则该子序列的起始位置就在下一位i + 1.

int start = 0;
for (int i = end; i >= 0; i--)
{
    //第一个dp[i]==0的下一位是起始位置
    if (dp[i] == 0)
    {
        start = i + 1;
        break;
    }
}

接下来就是打印结果了:

//打印dp数组
cout << "打印dp数组:"  << endl;
for (int i = 0; i < SIZE; i++)
{
    cout << dp[i] << " " ;
}
//打印最大连续子序列:
cout << "打印最大连续子序列" << endl;
for (int i = start; i <= end; i++)
{
    cout << arr[i] << endl;
}

综上所述:

#include <iostream>

using namespace std;

//描述问题规模(数组长度)
#define SIZE sizeof (arr) / sizeof(arr[0])

//问题描述(要求子序列的数组)
int arr[] = {0, -2, 11, -4, 13, -5, -2};
//动态规划数组
int dp[sizeof (arr) / sizeof (arr[0])];

void solve()
{
    //初始化dp[0]
    dp[0] = 0;
    for (int i = 0; i < SIZE; i++)
    {
        //求dp[]数组第i个元素的值
        dp[i] = dp[i - 1] + arr[i];
        //如果dp[i]的值小于0,则放弃,从第i+1个再重新选
        if (dp[i] <= 0)
        {
            dp[i] = 0;
        }
    }
    
    //找到最大值的下标
    int end = 0;
    for (int i = 0; i < SIZE; i++)
    {
        if (dp[end] < dp[i])
        {
            end = i;
        }
    }

    //溯源,找到起始位置
    int start = 0;
    for (int i = end; i >= 0; i--)
    {
        //第一个dp[i]==0的下一位是起始位置
        if (dp[i] == 0)
        {
            start = i + 1;
            break;
        }
    }
    
    //打印dp数组
    cout << "打印dp数组:"  << endl;
    for (int i = 0; i < SIZE; i++)
    {
        cout << dp[i] << " " ;
    }
    cout << endl;
    
    //打印最大连续子序列:
    cout << "打印最大连续子序列: " << endl;
    for (int i = start; i <= end; i++)
    {
        cout << arr[i] << endl;
    }
}

int main(void)
{
    solve();
    
    return 0;
}

输出结果:

打印dp数组:
0 0 11 7 20 15 13
打印最大连续子序列:
11
-4
13

标签:11,arr,规划法,13,数组,序列,动态,dp
From: https://www.cnblogs.com/codels/p/18226267

相关文章

  • 《探索时间序列预测——电力系统负荷预测之谜》
             下述链接均可点击跳转,手机端打开速度较慢!请耐心等待哦~专题推荐:论文推荐,代码分享,典藏级代码,视角(点击即可跳转)更新啦!高创新组合模型和算法典藏级matlab代码(电力系统优化和时间序列预测方向)倾情推送24.5.29【代码推荐购买指南】电力系统运行优化与规划、......
  • FreeRTOS基础(三):动态创建任务
       上一篇博客,我们讲解了FreeRTOS中,我们讲解了创建任务和删除任务的API函数,那么这一讲,我们从实战出发,规范我们在FreeRTOS下的编码风格,掌握动态创建任务的编码风格,达到实战应用!目录一、任务函数二、动态创建任务的基本步骤2.1使能FreeRTOS的API函数2.2 定义动态创......
  • 基于CNN+LSTM深度学习网络的时间序列预测matlab仿真,并对比CNN+GRU网络
    1.算法运行效果图预览  2.算法运行软件版本MATLAB2022A  3.算法理论概述      时间序列预测是数据分析中的一个重要分支,它涉及到对未来事件的预测,基于历史数据中的模式和趋势。在深度学习领域,卷积神经网络(CNN)和循环神经网络(RNN)的组合,特别是结合长短时记忆......
  • 在Spring中实现资源的动态加载和卸载
    在Spring框架中,实现资源的动态加载和卸载通常涉及以下几个方面:1.使用@Bean注解动态注册Bean通过在配置类中使用@Bean注解,可以在运行时动态创建和注册Bean。@ConfigurationpublicclassDynamicBeanConfig{@BeanpublicMyBeanmyBean(){//创建并......
  • 673. 最长递增子序列的个数
    673.最长递增子序列的个数给定一个未排序的整数数组nums,返回最长递增子序列的个数。注意这个数列必须是严格递增的。示例1:输入:[1,3,5,4,7]输出:2解释:有两个最长递增子序列,分别是[1,3,4,7]和[1,3,5,7]。示例2:输入:[2,2,2,2,2]输出:5解释:最长递增子序......
  • 基于对比稀疏扰动技术的时间序列解释框架 ContraLSP
    开篇近日,由阿里云计算平台大数据基础工程技术团队主导,与南京大学、宾夕法尼亚州立大学、清华大学等高校合作,解释时间序列预测模型的论文《ExplainingTimeSeriesviaContrastiveandLocallySparsePerturbations》被机器学习领域顶会ICLR2024接收。该论文提出了一种创新的基......
  • OR-Tools CP-SAT:如何为动态能力和任务建模
    我正在处理作业车间调度问题,其中我有一些定义为时间间隔变量的任务:IntervalVartaskInterval=model.NewIntervalVar(start,duration,end,$"interval_{task.WorkOrder_Id}_{task.TaskId}");每个任务都可以在某个工作站上完成,每个工作站都有自己的日历。List<UserCalendarsDTO>......
  • Leedcode-最长特殊序列 Ⅰ
    自己写的:classSolution:#getMinimumDifference方法接收一个二叉树的根节点root,并返回树中所有节点值的最小差值defgetMinimumDifference(self,root:Optional[TreeNode])->int:#初始化一个列表用于存储树中的节点值myli=[]#使......
  • 【C语言】动态内存管理
    前言为什么要有动态内存分配?可以回想一下目前为止,我们想要向内存申请一块空间存放数据,有哪些手段呢?目前我们遇到的方式主要有两种:一、创建一个变量。比如我们存放一个整型数据,就创建一个整型变量。(也就是申请4个字节)我们创建一个变量,存放了一个数据。intn=2077;二、如......
  • 长序列中Transformers的高级注意力机制总结
    在处理长序列时,Transformers面临着注意力分散和噪音增加等挑战。随着序列长度的增长,每个词元必须与更多词元竞争注意力得分,这会导致注意力分数被稀释。这种稀释可能导致不那么集中和相关的上下文表示,特别是影响彼此距离较远的词元。并且较长的序列更有可能包含不相关或不太相关的......