HDU1003 Max
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003
题目大意:最大子段和,求连续的ai中和最大的
题目思路:这道题想明白了很简单,一个简单的动态规划。所有的子数列,可以按照“以a[i]为结尾”的规则分成n组
第一组为a[1],
第二组为a[1],a[2] 与a[2]
第三组为a[1],a[2],a[3]与a[2],a[3]与a[3]
……
我们要求的最大值,只要将这n组的最大值求出,然后再求出n个最大值中的最大值即可。
记dp[i]为第i组的最大值,那么
dp[1] = max{a[1]} = a[1];
dp[2] = max{a[1] + a[2], a[2]} = max{dp[1] + a[2], a[2]};
dp[3] = max{a[1] + a[2] + a[3], a[2] + a[3], a[3]}= {dp[2] + a[3], a[3]};
……
则可归纳出dp[i] = max{dp[i - 1] + a[i], a[i]};(其中1 ≤ i ≤ n)
接下来要求始末位置,
仔细一想,当我们取最大值取得是dp[i - 1] + a[i]的时候,始位置不变,末位置变成了i,当我们取a[i]时,始末位置都变成了i。
然后题目要求取第一个出现的最大值,那么if(dp[i - 1] + a[i] > a[i]) 的等号要取。
#include<cstdio>
#include<cstring>
const int maxn = 100004;
int a[maxn];
int dp[maxn];
int main()
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
{
if(i != 1){
printf("\n");
}
memset(a, 0, sizeof(a));
int t;
scanf("%d", &t);
int maxx = -100000;
int ff = 1,ll = 1;
int first = 1, last = 1;
for(int j = 1; j <= t; j ++)
{
scanf("%d", &a[j]);
if(j == 1)
{
dp[j] = a[j];
}
else
{
if(dp[j - 1] + a[j] >= a[j]){
dp[j] = dp[j - 1] + a[j];
last = j;
}
else {
dp[j] = a[j];
first = j;
last = j;
}
}
if(dp[j] > maxx)
{
maxx = dp[j];
ff = first;
ll = last;
}
}
printf("Case %d:\n%d %d %d\n", i,maxx,ff,ll);
}
}