轉載自http://blog.chinaunix.net/uid-24922718-id-4848418.html
有這麼一類問題,需要在給的一組數據中找到不大於某一個上限的“最優連續子序列”
於是就有了這樣一種方法,找這個子序列的過程很像毛毛蟲爬行方式比較流行的叫法是“尺取法”。
Poj3061
給長度爲n的數組和一個整數m,求總和不小於m的連續子序列的最小長度
輸入
n = 10,m = 15
5 1 3 5 10 7 4 9 2 8
輸出
2
那麼我們先用sum存當前這個子序列的和,從左邊第一個數來存,直到這個子序列的和大於等於m爲止,再記錄下當前長度。
其實相當於當不滿足條件就入隊,然後得到隊列長度,再將隊首元素出隊,再進行下一次的入隊,直到滿足條件再次出隊,並且將這一次的長度與歷史最短長度進行取捨,最後掃到最後的元素卻無法再滿足入隊條件的時候就結束,此時用O(n)的時間就可以得到答案。
如下,我把樣例用毛毛蟲爬一遍,紅色的是當前“毛毛蟲着地”也就是剛好滿足題意的子序列的地方:
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
//代碼如下
#include<stdio.h>
int MIN(int x,int y)
{
return x>y?y:x;
}
int main()
{
int n,mmax,ans,i,j,sum,m,a[10000];
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&n,&mmax);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
ans=n+1; //步數
i=0;
j=0;
sum=0;
while(1)
{
while(j<n&&sum<=mmax) //滿足條件一直sum+
sum+=a[j++];
if(sum<mmax)break; //證明j>n 但是 sum<mmax -->沒有滿足條件的長度
ans=MIN(j-i,ans); //滿足條件,ans-->步數的最小值
sum-=a[i++]; //類似於出隊
}
if(ans>n)
ans=0;
printf("%d\n",ans);
}
}