【LIS】HDU - 1003 Max Sum 简单易懂的讲解

这篇博客详细讲解了如何使用动态规划解决HDU 1003 Max Sum问题。通过动态规划数组dp[i]记录到位置i的最大子序列和,根据dp[i-1]的值判断是否包含当前元素a[i],并给出两种情况的策略:当dp[i-1]<0时,dp[i]=a[i];当dp[i-1]>=0时,dp[i]=dp[i-1]+a[i]。博主提供了参考代码来辅助理解。

HDU - 1003 Max Sum

解题思路

动态规划, d p [ i ] dp[i] dp[i] 记录到位置 i i i 的最大子序列和。

判断过程中,有两种情况:

  • d p [ i − 1 ] < 0 dp[i - 1] < 0 dp[i1]<0 :可以这么理解,前面的最大和都是负数了, 我 a [ i ] a[i] a[i] 为什么还要去瞎掺和?

    我如果是负数,加进去肯定使得 d p [ i ] dp[i] dp[i] 更小了,不划算;我如果是正数,加进去也不划算,相当于莫名其妙被减了一点,还不如另辟蹊径重新开始算。因此这种情况,采取策略: d p [ i ] = a [ i ] dp[i] = a[i] dp[i]=a[i]

  • d p [ i − 1 ] > = 0 dp[i - 1] >= 0 dp[i1]>=0:那就正常算,因为 d p [ i ] dp[i] dp[i] 表示的是到当前位置的最大和,那么 a [ i ] a[i] a[i] 总归是要算进来的,即 d p [ i ] = d p [ i − 1 ] + a [ i ] dp[i] = dp[i - 1] + a[i] dp[i]=dp[i1]+a[i]

遍历的过程中,更新答案即可。

参考代码

#include<stdio.h>
#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
//#define LOCAL  //提交时一定注释
#define VI vector<int>
typedef long long LL;
typedef double db;
const int inf = 0x3f3f3f3f;
const LL INF = 1e18;
const int N = 1e3 + 10;
using namespace std;
const int mod = 1e9 + 7;
const int M = 1e5 + 10;
const int base = 400;
int readint() {int x; scanf("%d", &x); return x;}

int dp[M], a[M];

void init() {
    dp[0] = -1;  //这个是方便后面写代码,dp[1]就不用特殊处理了
}

int main() {
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
//   freopen("output.txt", "w", stdout);
#endif
    int t = readint();
    for(int ca = 1; ca <= t; ca++) {
        init();
        int n = readint();
        for(int i = 1; i <= n; i++)
            a[i] = readint();
        int ans = -inf, s, e, ansl, ansr;
        for(int i = 1; i <= n; i++) {
            if (dp[i - 1] < 0) {  //另辟蹊径
                dp[i] = a[i];
                s = e = i;  //更新开始、结束的位置
            }
            else {
                dp[i] = dp[i - 1] + a[i];
                e = i;
            }
            if (dp[i] > ans) {  //更新答案
                ans = dp[i];
                ansl = s, ansr = e;
            }
        }
        if (ca > 1) printf("\n");
        printf("Case %d:\n", ca);
        printf("%d %d %d\n", ans, ansl, ansr);
    }

    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值