尺取--(毛毛蟲演算法)
阿新 • • 發佈:2022-03-11
尺取--(毛毛蟲演算法)
尺取演算法也叫毛毛蟲演算法,因為計算過程有點類似毛毛蟲一點點的往前挪,在挪動的過程中可以得到一些需要的解。(自動腦補)
通過兩個變數來儲存所選取區間的左右端點,然後不斷的推進區間,尋找所需要的答案(尺取的精髓),其實也是一種暴力列舉方法,不過是有技巧的列舉,所以尺取演算法比一般的演算法快的多,尤其是資料量比較大的時候,尺取就顯得非常有用,所以也是acm經常用到的演算法之一。
通過一個例題來理解這個演算法
冬天與火鍋更配
冬日裡的一抹暖陽總是能給人們留下深刻的記憶,人們喜愛冬天的太陽,就跟人們喜愛冬天的火鍋一般。
寒冷的冬天總會讓人想起火鍋,最近小Z特別想去吃火鍋,剛好某家轉轉火鍋剛開業有活動,有n盤火鍋圍成一個圈,第一盤和最後一盤是相連的,每一盤火鍋都有一個價值a[i],現在可以吃連續的m盤火鍋,小Z想知道他所吃的那連續的m盤火鍋的最大價值可以是多少?你能幫幫憨憨的小Z嗎。
輸入格式
第一行數入兩個整數n,m(1<=m<=n<=2000000),分別表示火鍋的盤數和可以吃的連續的盤數
第二行輸入n的數a[i] (1<=a[i]<=100000),分別表示每一盤火鍋的價值
輸出格式
輸出一個整數,表示連續m盤火鍋的最大價值
樣例輸入
5 3
6 1 2 5 3
樣例輸出
14
分析:
這個題實際就是求連續m個數和的最大值,想必很多人也是一開始暴力模擬一遍,然後提交是時間超限,這裡最壞的時間複雜度是O(n^2),這個題的資料量比較大,所以考慮用尺取。
下面看一下核心程式碼
#include<stdio.h> int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { int a[n]; int t=0;//表示推進的m int tail=0;//表示毛毛蟲的尾巴 long long max1=-1;//所求的最大值 long long sum=0; for(int i=0;i<n;i++) scanf("%d",a+i); while(1)//尾巴不爬到最後就一直往前爬 { while(t<m)//毛毛蟲向前爬m個位置 { int tt=tail+t; if(tt>=n)//頭爬到最後得到第一個位置去 tt%=n; sum+=a[tt]; t++; } if(sum>max1)max1=sum; sum-=a[tail];//得到一次連續m個數和之後減去尾巴的值 tail++;//尾巴向前挪一個 if(tail==n-1)break;//如果尾巴到了最後一個就可以退出了 t--;//長度減一(尾巴) } printf("%lld\n",max1); } }
可以看出尺取把原來的時間複雜度O(n2)變成了O(n),在效率上得到了很多的提高。