HDU 1231 最大连续子序列( DP做法 + 水题做法)

原题链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1231

感谢美辰学长的指导

DP做法代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int N;
int a[10050]; //存放每一个输入数
int b[10050]; //存放以i结尾的最大和

int main()
{
    while( ~scanf("%d",&N) )
    {
        if( N == 0 ) break;
        int i;
        for( i = 1; i <= N; i++ )
            scanf("%d",&a[i]);
        b[0] = 0;
        int last = 1;  //临时记录以i结尾的最大子序列的开头位置
        int max_last = 1; //保存以i结尾的最大子序列的开头位置
        int Max = -1; 
        for( i = 1; i <= N; i++ )
        {
          //b[i]的值就两种情况。要么从前一点接到这一点。要么从自己这点重新开始
            b[i] = b[i-1] + a[i] > a[i] ? b[i-1] + a[i] : a[i];
            //判断是否从该点重新开始
            if( b[i] == a[i] )
                last = i;
            //题目要求要输出的序号最小的i,j。所以只有b[i]的值比max大。才将max_last的值修改
            if( b[i] > Max )
            {
                max_last = last;
                Max = b[i];
            }
        }
        int k,f;
        f = 0;
        Max = -1;
        //最大子序列的头开始寻找。找到从max_last到N之间的b[i]的最大值
        for( i = max_last; i <= N; i++ )
        {
        //判断是否整列数都为负数
            if( b[i] >= 0 )
                f = 1;

            if( f )
            {
            //max的初始值为0.即使没有大于0的数。也可以输出含有负数和0的情况
                if( b[i] > Max )
                {
                    k = i;
                    Max = b[i];
                }
            }
        }
        if( !f )
            printf("0 %d %d\n",a[1],a[N]);
        else
            printf("%d %d %d\n",Max,a[max_last],a[k]);

    }
    return 0;
}

水题做法代码如下:

水体做法思路:

每次对tmp的值做判断
tmp > 0 判断 :
是否大于 res(对应值做修改)

tmp = 0 判断
res是否等于0(判断之前有没有出现过负数)
a[i]是否等于0(判断这一项是否为0)

tmp < 0 判断
res是否等于0(是否出现过正数(是否整列都是负数))

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int N;
int a[10050];

int main()
{
    int f;
    while( ~scanf("%d",&N))
    {
        if( N == 0 ) break;
        int i;
        f=0;
        for( i = 1; i <= N; i++ )
            scanf("%d",&a[i]);
        int fs,fe,res,tmp;
        int ts,te;
        fs = fe = ts= te = 1;
        res = tmp = 0;
        for( i = 1; i <= N; i++ )
        {
            tmp = tmp + a[i];
            if ( tmp > 0 )
            {
                te = i;
                if( tmp > res )
                {
                    res = tmp;
                    fs = ts;
                    fe = te;
                }
            }

            else if ( tmp == 0 )
            {
                //之前没有出现过正数
                if( res == 0 )
                {
                    if( a[i] == 0 )
                    {
                        f=1;
                        fs = ts = i;
                        fe = te = i;
                    }
                    else
                    {
                        fs = ts = i + 1;
                        fe = te = i + 1;
                    }
                }
                //之前已经找到一段最小区间
                if( res != 0 )
                {
                    if( a[i] == 0 )
                    {
                        ts = te = i;
                    }
                    else
                    {
                        ts = te = i + 1;
                    }
                }
            }
            else if( tmp < 0 )
            {
                if( res == 0 )
                {
                    tmp = 0;
                    fs = ts = i + 1;
                    fe = te = i + 1;
                }
                else
                {
                    tmp = 0;
                    ts = i + 1;
                    te = i + 1;
                }
            }


        }

        //输出部分
        // res = 0表示没有出现过正数
        if( res == 0 )
        {
            //不存在正数。但是存在0.
            if( f )
            {
                printf("0 0 0\n");
                continue;
            }
            //整列都是负数
            if( fe == fs && fe >= N && a[N] != 0 )
            {
                printf("0 %d %d\n",a[1],a[N]);
                continue;
            }
        }
        else
            //正常情况输出
            printf("%d %d %d\n",res,a[fs],a[fe]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值