这几天做我们学校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;
}