这几天做我们学校acm上的一道题,一直超时,实在想不出什么好办法了,请各位大虾帮帮忙
做个链接,这下面是原题,其实也不是严格的求“和最大子序列”,不过很类似
http://acm.hit.edu.cn/ojs/show.php?Proid=1760&Contestid=0
我的代码如下,比较烦,可不看~~
/*
 *Organization: Harbin Institute of Technology
 *Author: David
 *Date: From 2007-4-20 18:52:44
 *Description: acm.hit Problem 1760
 *Background: 今天看了两集一公升的眼泪
 *实质: 求和最大子序列(并不严格)
 */
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10000
int label_of_pst (int*, int);               /*功能:求一组数正数出现的首位置
                                             *参数:为一个数组,和数组的大小
                                             *返回:正数出现在该数组的首位置
                                             */
int search_for_longest (int*, int, int);    /*
                                             *功能:求和最大子序列
                                             *参数:数组首地址,要计算的数组大小,想处理的第一个元素的地址
                                             *返回:最大的和
                                             */
int main (void)
{
    int num, result = 0;                    /*num——数组的大小,result——最后的输出结果*/
    int i = 0, j = 0, k = 0;                /*3个for循环里的变量*/
    int arr[SIZE], b[SIZE];                 /*arr储存第一个数组,b储存处理后的arr*/
    scanf("%d", &num);
    while (num != 0)                        /*当数组个数为0时,结束程序*/
    {
        for (i = 0; i <= num - 1; i++)
        {
            scanf ("%d", &arr[i]);          /*把原始数组读进arr*/
        }
        k = label_of_pst(arr, num);         /*第一个正数出现在原始数组中的位置*/
        if (k == -1)                        /*原始数组中没有正数,重新读数组*/
        {
            scanf("%d", &num);
            continue;
        }
        else                                /*这个else把相邻的正数,负数分别加起来,存入b中*/
        {
            for (i = k; i <= num -1; i++)   /*从第一个正数开始,前面的负数忽略*/
            {
                b[j] += arr[i];
                if (i == num - 1)           /*如果加到了最后一个数,就退出这个for循环*/
                {
                    j++;          /*把这个for循环看完就明白这个if里的几个语句*/
                    break;
                }
                else                        /*没有到达最后一个数的时候,执行这个else语句*/
                {
                    if (b[j] * arr[i + 1] >= 0)   /*当"和"与后面一个数符号相同的时候继续加
                                                     *注意,因为这里有与“后面一位”的运算,
                                                     *为了避免数组越界(即数组的最后一位与“后面
                                                     *一位”运算),才有了上面的if(i == num - 1)
                                                     */
                    {
                        continue;
                    }
                    else                   /*当“和”与后面一个数的符号不相同的时候,把“和“储存到b
                                            *的一个元素中*/
                    {
                        j++;
                        continue;
                    }
                }
            }
            if (b[j - 1] < 0)               /*保证数组b的最后一个元素为正,方便以后操作*/
            {
                j--;
            }
            else
            {
                ;
            }
        }
        result = search_for_longest (b, j, 0);  /*该函数返回输出的结果, j为要计算的数组大小*/
        printf ("The maximum winning streak is %d.\n", result);
        for (i = 0; i <= j; i++)
        {
            b[i] = 0;                             /*把b初始化*/
        }
        j = 0;                                    /*初始化变量*/
        result = 0;
        scanf("%d", &num);                        /*读完继续循环*/
    }
    return 0;
}
/*
 *define label_of_pst
 */
int label_of_pst (int *arr, int num)
{
    int i;
    for (i = 0; i <= num - 1; i++)
    {
        if (arr[i] >= 0)
        {
            return i;       /*检查到第一个正数,返回该正数在数组中所在的位置*/
        }
        else
        {
            ;               /*do nothing*/
        }
    }
    printf ("Losing streak.\n");     /*如果没有正数,打印结果,返回-1,使main函数判断后结束*/
    return -1;
}
/*
 *define search_for_longest
 */
int search_for_longest (int *b, int length, int begin)
{
    int i, j, k;                       /*for循环中的3个变量*/
    int sum = 0, result = 0;        /*sum为b数组中几个数的和,result为返回值*/
    int hold;
    for (i = 1; i <= length; i += 2)
    {
        for (j = begin; j <= i - 1 + begin; j++)
        {                                         /*该for循环得出b中1,3,5……个元素相加的和的最大值
                                                   *当然,从哪里开始与begin有关
                                                   *从begin开始,第一次把1个数相加,第二次3个……*/
            sum += b[j];
        }
        if (sum > result)                        /*如果sum大于result,result取sum的值*/
        {
            result = sum;
            sum = 0;
            continue;                            /*初始化sum,便于以后再用*/
        }
        else
        {
            ;                                    /*do nothing*/
        }
    }
    if (length != 1)                            /*用递归计算以下一个正数开始的b的情况*/
    {
        for(i = 2, hold = 0; i <= length - 1; i += 2)
        {                                               /*这个for循环用来实现当一个正数加上相邻一个
                                                         *负数的和大于下一个正数的时候,不考虑下一个
                                                         *正数开始的递归,因为他求出的最大的值始终小
                                                         *于前一个整数进行相关操作后的最大值
                                                         */
            for (k = begin; k <= i - 1 + begin; k++)
            {
                hold += b[k];                           /*hold用于储存相邻几个数的和*/
            }
            if(b[k] > b[k + 1])
            {
                ;
            }
            else
            {
                length -= 2;
                begin += 2;
            }
        }
        sum = search_for_longest (b, (length - 2), (begin + 2));
    }
    else
    {
        ;
    }
    if (sum >= result)
    {
        result = sum;
        sum = 0;
    }
    else
    {
        sum = 0;
    }
    return result;
}
 
										
					
	
 
											





 
	    
