解题思路
动态规划, d p [ i ] dp[i] dp[i] 记录到位置 i i i 的最大子序列和。
判断过程中,有两种情况:
-
d p [ i − 1 ] < 0 dp[i - 1] < 0 dp[i−1]<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[i−1]>=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[i−1]+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;
}
这篇博客详细讲解了如何使用动态规划解决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]。博主提供了参考代码来辅助理解。
150

被折叠的 条评论
为什么被折叠?



