题目(1):
众所周知,沫沫以火锅为生。在E8的聚餐活动中,他经常卖萌卖无辜领着大家吃火锅。。
有一天,沫沫听说学校附近的哺呷哺呷在某现充的赞助下有一个优惠活动,只需30软妹币,对每个客人,它会上N道菜,但是客人只能挑选其中连续上的一些菜。
于是他非常兴奋的拉着灰灰和渣渣去吃火锅去啦。
沫沫是一个十分挑食的人,所以他对每一道菜都有一个愉快度(当然因为他的挑食,某些事物的愉快度会是负数)。
为了让沫沫能非常愉快的享受这次聚餐,善解人意的灰灰和渣渣决定帮他计算,他们应该怎么选择菜才能使沫沫最开心地吃完这次聚餐。
输入格式:
第一行是一个整数T,(T <= 10)表示测试案例的个数
对于每个测试案例,第一行是一个整数N,( 1<=N <= 10000)表示菜的个数
接下来的N个数字,第i个数字si表示沫沫对第i道菜的愉快度。( -1000 <=si <= 1000)
PS:由于CF又被血虐掉rating,所以沫沫的起始愉快度是0
PPS:沫沫完全可能得到一个为负值的愉快值, poor 沫沫。。
输出格式:
对于每个样例,输出一个数字,表示沫沫吃完之后愉快度的最大值。
HINT:
对于 5
6 -1 5 4 -7
我们选择6, -1, 5, 4这四道菜(注意必须是连续的,所以不能跳过-1)
分析:
题目要实现的是“连续一段输入和的最大值”。所以我们的思路可以是:从第一个数加到第二个数、第三个数……最后加到第n个数,再从第二个数加到第三个数、第四个数……第n个数,找出其中和的最大值。
这个思路的实现结果:
1 #include<stdio.h> 2 int main() 3 { 4 int a[10001]={0}; 5 int n,x,i,j,k; 6 int count=0; 7 scanf("%d",&n); 8 int sum=0; 9 10 while(count<n) 11 { 12 int max=-1001; 13 scanf("%d",&x); 14 for(i=1;i<=x;i++) 15 { 16 scanf("%d",&a[i]); 17 } 18 for(i=1;i<=x;i++) 19 { 20 for(j=i;j<=x;j++) 21 { 22 for(k=i;k<=j;k++) 23 { 24 sum+=a[k]; 25 } 26 if(sum>max) 27 { 28 max=sum; 29 } 30 sum=0; 31 } 32 } 33 printf("%d\n",max); 34 count++; 35 } 36 }
当然对于本题这个方法似乎速度不是很快,并且可以有不用数组的方法,如下:
1 #include<stdio.h> 2 int main() 3 { 4 int x,n,t,s,m,max=-1001; 5 scanf("%d",&t); 6 while(t--) 7 { 8 scanf("%d",&n); 9 s=m=0; 10 while(n--) 11 { 12 scanf("%d",&x); 13 if(max<x) max=x; 14 if(m+x>0) m=m+x; 15 else m=0; 16 if(s<m) s=m; 17 } 18 if(max<0) printf("%d\n",max); 19 else printf("%d\n",s); 20 } 21 }
思路大致为:
设置了两个记录性的中间变量:s,m;
s:记录已经出现sum的最大值;
m:已经出现sum的最大值加上下一个输入的值,
若结果小于零,则m=0(放弃之前的所有操作);
若大于零,则判断与s的大小关系(加上下一个输入的值比原来得大还是比原来的小)。
第一种方法还具有一定的普适价值,例如可以用于计算等值数列问题。
题目(2):
如果一个数列中的某一段(至少有两个元素)的各元素值均相同,则称之为等值数列段。
等值数列段中元素的个数叫做等值数列段的长度。
输入:由 N个元素组成的整数数列 A(其中 N<=50)
输出:A 中长度最大的等值数列段的始末位置,如果没有等值数列段,则输出 No equal number list.
说明:始末位置是指数组下标,即0 表示第一个元素。
如果有多个同等长度的等值数列,只输出第一个等值数列的起始位置。
当在一个 LIST 中出现两个等长的连续串的时候,我们的答案应该是第一个等长串。
分析:这里提供了一种思路,
数组a[]:记录数据;
数组startPosition[]:记录等值数列起始位置;
数组count[]:记录等值数列有几个数字相等;
最终寻找count[]最大的一组等值数列。
1 #include<stdio.h> 2 int main() 3 { 4 int a[50]={0}; 5 int startPosition[50]={0}; 6 int count[50]={0}; 7 int N; 8 scanf("%d",&N); 9 10 int i=0; 11 int j=0; 12 for(i=0;i<N;i++) 13 { 14 scanf("%d",&a[i]); 15 } 16 17 for(i=0;i<N;i++) 18 { 19 if(a[i]==a[i+1]&&count[j]>0) 20 { 21 count[j]++; 22 } 23 else if(a[i]==a[i+1]&&count[j]==0) 24 { 25 startPosition[j]=i; 26 count[j]++; 27 } 28 else 29 { 30 j++; 31 } 32 } 33 34 int max=0; 35 int max_p=0; 36 for(j=0;j<N;j++) 37 { 38 if(count[j]>max) 39 { 40 max=count[j]; 41 max_p=startPosition[j]; 42 } 43 } 44 if(max>0) 45 { 46 printf("%d %d\n",max_p,max_p+count[max_p]); 47 } 48 else 49 { 50 printf("No equal number list.\n"); 51 } 52 53 }
我们也可以按照火锅问题的思路进行实践:
1 #include<stdio.h> 2 int main() 3 { 4 int N; 5 scanf("%d",&N); 6 int startPosition=0; 7 int count=0; 8 int i,j,k; 9 int a[50]={0}; 10 int sum=0; 11 12 for(i=0;i<N;i++) 13 { 14 scanf("%d",&a[i]); 15 } 16 for(i=0;i<N;i++) 17 { 18 for(j=i;j<N;j++) 19 { 20 for(k=i;k<=j;k++) 21 { 22 sum+=a[k]; 23 } 24 if(sum==(j-i+1)*a[k]) 25 { 26 if(j-i+1>count) 27 { 28 startPosition=i; 29 count=j-i+1; 30 } 31 } 32 sum=0; 33 } 34 } 35 if(count==0) 36 { 37 printf("No equal number list.\n"); 38 } 39 else 40 { 41 printf("%d %d\n",startPosition,startPosition+count); 42 } 43 }