题目描述
大森林有熊兄弟的好朋友松鼠蹦蹦,一天蹦蹦来到一条很长的小路,发现沿路地上都有松果,高兴极了,决定尽可能多吃松果。
蹦蹦观察到,每个松果的重量并不一定相同,可蹦蹦的肚子容量有限,总共最多只能吃重量C的松果。
蹦蹦吃东西有个特点,一旦开吃就会不停的吃,不会漏过路上碰到松果,直到遇到一个吃不下或吃完停止。也就是说松鼠蹦蹦只会吃连续一段的松果。
已知路上共有N个松果,顺序的重量是w1,w2,….wn。蹦蹦最多可能吃多少颗松果?
第一行,二个正整数,空格分开,表示N和C,N范围在[1..50000], C范围在[1..1000000]。
第二行,N个正整数,空格分开,表示从w1、w2,…wn,即松果的重量。每个松果重量范围在[1..1000]。
一个正整数,蹦蹦可以吃到的最多松果数量。
5 5
3 1 2 1 1
输入样例二:
9 5
1 5 4 3 2 1 1 4 1
输出样例一:
4
输出样例二:
3
所谓成功编出一道题,即使现在头脑里想出算法,再付之编程语言,但这是远远不够的。在大多数情况下,你最多也只能拿个七八十分,甚至更低,那就必须要我们重新看待题目和自己的程序,从而进行算法优化。
在看这题,一目了然,纯枚举,首先,你要设个变量i从一开始枚举到N,来确定开始点,再从i+1到N开始枚举,计算最能能有多少个连续数,这时间复杂度最大变成了多于5000×5000。老师说过,大于10*8就会超时。可这会超时,最多50分吧。
这时我们就必须对自己的算法进行优化。看看枚举在这题的缺点。就拿样例1来说吧,从3开始枚举,已经计算了1和3这两个数,到第二次从1开始枚举时,我们可以发现,重复计算了1。因此枚举重复计算了数字。最后导致了超时。
我们优化算法,就要从这点开始优化。
那么,要怎么优化呢?
我们可以设想把枚举的开始点和结束点连成一个窗口,看成是把窗口里的数相加。这么我们是否可以先设一个开始点,一个结束点,结束点往后移,把窗口里的数相加,直到窗口里面的数大于C,我们又把开始点向前挪一位,如果窗口里面的数还大于C又继续前移,直到小于C或等于C。设一个变量来保存最大连续数。
程序如下:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int a[50005],j=1,b,n,m,s,d;
int main()
{
freopen("1167.in","r",stdin);
freopen("1167.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++)//枚举
{
cin>>a[i];
s=s+a[i];
while(s>m)//开始点向前移
{
s=s-a[j];
j++;
}
d=max(d,i-j+1);//保存最大值
}
cout<<d;
return 0;
}