题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003
1003是喜闻乐见的最大连续子串和,经典的动态规划题目,经典归经典,我确实是刚刚做……在这道题中,我们需要保证的是在计算过程之中,计算的和是一直增加的,如果碰到了让和减少的元素,直接把和更新为0,并且更新临时首指针,每找到一个更优的解,把真正的首指针和尾指针更新,整个过程中一直保证的是和是递增的。注意我说的是非全负的情况。
#include <cstdio>
int sum, s, t, ss, maxn, a[100100];
bool f;
int main(){
int t, n, p;
scanf("%d", &p);
for (int k = 1; k <= p; k++){
scanf("%d", &n);
f = 0, maxn = -9999999; sum = 0;
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]);
if (a[i] >= 0) f = 1;
}
if (!f){
for (int i = 1; i <= n; i++)
if (a[i] > maxn){
maxn = a[i];
s = i;
}
printf("Case %d:\n%d %d %d\n", k, maxn, s, s);
}
else{
s = 1; t = 1; ss = 0;
for (int i = 1; i <= n; i++){
sum += a[i];
if (sum < 0){
ss = i;
sum = 0;
}
else if (sum > maxn){
maxn = sum;
s = ss + 1;
t = i;
}
}
printf("Case %d:\n%d %d %d\n", k, maxn, s, t);
}
if (k < p) printf("\n");
}
return 0;
}
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1024
这道题厉害了,要求在n个数里面求m个最大子段和,要求最终的和最大,其实就是计算m次,因为这此不用记录区间的首尾元素,所以其实比上一道题好写一些。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1000100;
int n, m, ans, a[maxn], f[maxn], g[maxn];
int main(){
while (~scanf("%d%d", &m, &n)){
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
memset(f, 0, sizeof(f));
memset(g, 0, sizeof(g));
for (int i = 1; i <= m; i++){
ans = -100 * maxn;
for (int j = i; j <= n; j++){
f[j] = max(f[j - 1], g[j - 1]) + a[j];
g[j - 1] = ans;
ans = max(ans, f[j]);
}
}
printf("%d\n", ans);
}
return 0;
}