hdu 1231

来源:互联网 发布:如何测试网络的连通性 编辑:程序博客网 时间:2024/04/28 19:00

题目概述

给定一个有N个数的数列,求最大连续子序列和及该子序列的首尾元素
若序列元素全负,则其最大和为0,首尾元素为给定序列的首尾元素
若多有个子序列和相等,输出首尾元素序号最小的

时限

1000ms/2000ms

输入

每组数据第一行正整数N,下一行N个整数,为序列中元素,输入到N=0为止

限制

1<=N<10000

输出

每行三个数,子序列和,子序列首元素值,子序列末元素值

样例输入

6
-2 11 -4 13 -5 -2
10
-10 1 2 3 4 -5 -23 3 7 -21
6
5 -8 3 2 5 0
1
10
3
-1 -5 -2
3
-1 0 -2
0

样例输出

20 11 13
10 1 4
10 3 5
10 10 10
0 -1 -2
0 0 0

讨论

基本思路和hdu 1003差不多,阶段,遇到的每一个数,状态,以该数结尾的子序列和,决策,将该数加入到之前的子序列和中,或作为新的子序列,子问题,到当前遇到的数为止的最大连续子序列和,子问题边界,遇到第一个数时的最大连续子序列和,无后效性确认,前面选的是什么数和后面一点关系都没有,确定参数,和dp,这个数本身i,从状态观察到最优方案是比较dp和0的大小,将这个数加到较大者上作为新dp值,同样观察到最优决策仅与前一个阶段有关,故dp没必要以数组形式呈现,但由于到最后一阶段时dp仅可体现最后一部分子序列的和,因而需要额外变量most记录最大和,基本思路已经很清晰了,下面处理细节问题
题目要求输出构成最大和的首尾元素值,故考虑更新dp值时一并记录首尾值,当加到之前和时,仅需更新尾元素,当从0重新加和时,需要同时更新首尾元素,对于最大和most,则仅当需要更新most值时一并更新首尾元素
题目要求序列全负时要以整个序列首尾元素输出,故需讨论序列是否全负,考虑到最大的负数是-1,若全负,不会有大于-1的数,故初始化dp和most为-1,且其值不应被更新为非负数,输出时,按most值是否为负数作为两种输出
题目还要求,若最大和相同,则首尾元素应输出较早出现的子序列的,由此可分析出,需要对most值的更新加以限制,由于先出现的符合题意,故将most值更新条件改为dp>most,仅当和严格大于最大和时,才更新最大和及首尾元素,至此,所有题目要求分析完成,可以出代码了

题解状态

187MS,1712K,796B,C++

题解代码

#include<algorithm>#include<cstring>#include<cstdio>using namespace std;#define INF 0x3f3f3f3f#define MAXN 10003#define memset0(a) memset(a,0,sizeof(a))void fun(int N){    int first = INF, last, dp = -1, l, r, most = -1, left, right;//first和last记录第一个和最后一个数 初值INF用来判别first是否已经修改过 dp,l和r记录上一序列的和及其首尾元素 most,left和right用于记录最大和及其子序列首尾元素    for (int p = 0; p < N; p++) {        int i;        scanf("%d", &i);//input        if (first == INF)//此时first尚未修改过            first = i;        last = i;        if (dp >= 0) {            dp += i;            r = i;        }        else {//dp初值为-1 因而会先更新首尾元素            dp = i;            l = r = i;        }        if (dp > most) {            most = dp;            left = l;            right = r;        }    }    if (most < 0)//序列全负 most值始终为-1        printf("%d %d %d\n", 0, first, last);//output    else        printf("%d %d %d\n", most, left, right);//output}int main(void){    //freopen("vs_cin.txt", "r", stdin);    //freopen("vs_cout.txt", "w", stdout);    int N;    while (~scanf("%d", &N) && N) {//input        fun(N);    }}

EOF

0 0
原创粉丝点击