最大子段和 dp

题目链接

#include<iostream>
#include<cstring>
#include<cstdio>
#define mem(a,b) memset((a),b,sizeof(a))
const int inf=1e9+10;
typedef long long ll;
const int N=100010;
using namespace std;
int a[1010];
int dp[1010][1010];
int main()
{
    int n;
    scanf("%d",&n);
    int maxn=-inf;
    for(int i=1;i<=n;i++)
        {scanf("%d",&a[i]);}
    for(int i=1;i<=n;i++)
        maxn=max(maxn,a[i]);
    if(maxn<0)
        {printf("%d",maxn);return 0;}
    int maxx=maxn;
    int tmp=0;
    int l=1,r=n;
    for(int i=1;i<=n;i++)
    {
        tmp+=a[i];
        if(tmp<0)
        {
            l=i+1;
            tmp=0;
        }
        if(tmp>maxx)
        {
            maxx=tmp;
            r=i;
        }
    }
    if(tmp>maxx)
        {maxx=tmp;r=n;}
    printf("%d",maxx);
    return 0;
}

 

<think>我们正在讨论使用动态规划(DP)算法求解最大问题。根据引用内容,动态规划是解决多阶决策问题的一种方法,其中每个阶的决策依赖于前一个阶的状态。最大问题要求在一个整数序列中找到一个连续序列,使得其最大。 动态规划解法的关键步骤: 1. 确定状态:定义dp数组,其中dp[i]表示以第i个元素结尾的最大。 2. 状态转移方程:考虑是否将当前元素加入到前一个中,或者单独作为一个开始。转移方程可以写为:$dp[i] = \max(a[i], dp[i-1] + a[i])$。意思是,以第i个元素结尾的最大要么是当前元素本身,要么是以前一个元素结尾的最大加上当前元素。 3. 初始化:dp[0] = a[0],因为只有一个元素时,最大就是该元素。 4. 遍历顺序:从数组的第一个元素遍历到最后一个元素。 5. 结果:dp数组中的最大值即为整个序列的最大。 此外,为了优化空间,我们可以只用一个变量来记录dp[i-1](称为当前最大连续),再用一个变量记录全局最大值。 下面我们用Python代码实现动态规划解法: ```python def max_subarray_sum(nums): if not nums: return 0 # 初始化当前最大 current_max = global_max = nums[0] # 从第二个元素开始遍历 for i in range(1, len(nums)): # 对于当前元素,决定是加入当前还是重新开始 current_max = max(nums[i], current_max + nums[i]) # 更新全局最大值 if current_max > global_max: global_max = current_max return global_max ``` 注意:上述代码考虑了所有元素为负数的情况,此时最大就是数组中的最大负数(单个元素)。 根据引用[3],还有一种分支法(分治法)可以求解最大问题,但动态规划是更常用且时间复杂度为$O(n)$的方法。 §§相关问题§§ 1. 动态规划求解最大的空间复杂度如何优化? 2. 如果要求输出最大对应的序列,应该如何修改代码? 3. 最大问题还有哪些其他解法?它们的时间复杂度分别是多少? </think>### 使用动态规划求解最大问题 最大问题要求在给定的整数序列中找到一个连续序列,使其元素最大。动态规划是解决该问题的高效方法,时间复杂度为$O(n)$,空间复杂度可优化至$O(1)$。 #### 动态规划解法步骤 1. **定义状态** 设$dp[i]$表示以第$i$个元素结尾的**最大**(必须包含$a[i]$) 2. **状态转移方程** $$ dp[i] = \max(a[i], \ dp[i-1] + a[i]) $$ - 选择$a[i]$单独作为 - 或接续前一个$(dp[i-1] + a[i])$ 3. **初始化** $dp[0] = a[0]$(首元素单独成) 4. **全局最大值** 遍历过程中记录全局最大值:$\text{max\_sum} = \max(\text{max\_sum}, dp[i])$ #### Python 代码实现 ```python def max_subarray_sum(nums): if not nums: return 0 dp = [0] * len(nums) # DP数组 dp[0] = nums[0] # 初始化 max_sum = dp[0] # 全局最大值 for i in range(1, len(nums)): # 状态转移:接续前或重新开始 dp[i] = max(nums[i], dp[i-1] + nums[i]) max_sum = max(max_sum, dp[i]) # 更新全局最大值 return max_sum ``` #### 空间优化版本(滚动变量) ```python def max_subarray_sum_optimized(nums): if not nums: return 0 current_max = nums[0] # 当前连续 global_max = nums[0] # 全局最大 for i in range(1, len(nums)): # 关键决策:是否抛弃前结果 current_max = max(nums[i], current_max + nums[i]) global_max = max(global_max, current_max) return global_max ``` #### 算法分析 - **时间复杂度**:$O(n)$ (单次遍历) - **空间复杂度**:$O(1)$(优化版本) - **核心决策**:当`当前 + a[i] < a[i]`时,说明前一拖累总,应丢弃前重新开始[^2][^3]。 > **示例**: > 输入序列:$[-2, 1, -3, 4, -1, 2, 1, -5, 4]$ > 动态规划过程: > | i | a[i] | current_max | global_max | > |---|---|---|---| > | 0 | -2 | -2 | -2 | > | 1 | 1 | max(1, -2+1)=**1** | 1 | > | 2 | -3 | max(-3, 1-3)=**-2** | 1 | > | 3 | 4 | max(4, -2+4)=**4** | 4 | > | 4 | -1 | max(-1, 4-1)=**3** | 4 | > | 5 | 2 | max(2, 3+2)=**5** | 5 | > | 6 | 1 | max(1, 5+1)=**6** | 6 | > 最终结果:最大为6(序列$[4,-1,2,1]$)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值