滾動陣列。。。。對於我這種不會用結果怕各種mle和各種tle的人來說確實是一向短處
(滾動的實質-膜法光輝【霧】)
吐槽不多說現在我們來看一下
乙個dp,平常如果需要1000×1000的空間,其實根據dp的無後效性,可以開成2×1000,然後通過滾動,獲得和1000×1000一樣的效果。滾動陣列常用於dp之中,在dp過程中,我們在由乙個狀態轉向另乙個狀態時,很可能之前儲存的某些狀態資訊就已經無用了,例如在01揹包問題中,從理解角度講我們應開dp[i][j]的二維陣列,第一維我們存處理到第幾個物品,也就是階段了,第二維儲存容量,但是我們獲得dp[i],只需使用dp[i - 1]的資訊,dp[i - k],k>1都成了無用空間,因此我們可以將陣列開成一維就行,迭代更新陣列中內容,滾動陣列也是這個原理,目的也一樣,不過這時候的問題常常是不可能縮成一維的了,比如乙個dp[i][j]需要由dp[i - 1 ][k],dp[i - 2][k]決定,i < n,0 < k < =10;n <= 100000000;顯然縮不成一維,正常我們應該開乙個dp[100000005][11]的陣列,結果很明顯,超記憶體,其實我們只要開dp[3][11]就夠了dp[i%3][j]由dp[(i - 1)%3][k]和dp[(i - 2)%3][k]決定,空間複雜度差別巨大
//經典的fib滾動
int fib[3];
int fib(int n)
return fib[2];
}
首先直觀地說,滾動陣列可以優化空間避免mle餐具
滾動陣列的作用在於優化空間,主要應用在遞推或動態規劃中(如01揹包問題)。因為dp題目是乙個自底向上的擴充套件過程,我們常常需要用到的是連續的解,前面的解往往可以捨去。所以用滾動陣列優化是很有效的。利用滾動陣列的話在n很大的情況下可以達到壓縮儲存的作用
其次附加帶來的一點,尤其對乙個大陣列賦值來說,滾動陣列可以優化時間避免tle
注意:這裡僅僅是對於某些特殊的問題優化時間,並非是降低了時間複雜度。實際上我們用滾動陣列是空間換時間的emmmm
相當於是你本來對10w個陣列賦值,由於滾動陣列,你可以把題目中的10w賦值變成乙個 < 10的陣列賦值,因為memset本來就很慢,你要是交給他那麼多工它很有可能愉悅的gg,因此對時間的優化性體現在這裡
經過滾動之後原本需要全部賦值的陣列小了不止一點半點,事實上相當於給乙個小的多的陣列賦值,這樣大大加快了時間,
滾動陣列雖好,但也存在一些不盡人意的地方,比如列印方案比較困難,當dp結束後,只有最後乙個階段的狀態值,而丟失了前面的值,事實上,對於01揹包問題下的,「前i個物品」這樣的規劃方向,只能使用逆向的列印方案,而且還不能保證它的字典序最小。所以在需要列印方案甚至要求字典序最小方案的場合要注意
還是我們之前所說的問題,那就是時間,換記憶體一定會犧牲時間。因此,滾動陣列一般用在時間比較充裕,而記憶體不夠的情況下(某些需要滾動的dp什麼的具體分析呀233)
滾動陣列可以通過取餘(%)來實現的,(實現乙個滾動|迴圈)
一維陣列的滾動操作
實現前:
int fib[3];
int fib(int n)
return fib[2];
}
實現後:
int main()
printf("%lld\n", d[79
%3]);
return
0;}
二維陣列的滾動操作
實現前:
int i, j, d[100][100];
for(i = 1; i < 100; i++)
for(j = 0; j
< 100; j++)
d[i][j] = d[i
-1][j] + d[i][j
-1];
實現後:
int i, j, d[2][100];
for(i = 1; i < 100; i++)
for(j = 0; j
< 100; j++)
d[i % 2][j] = d[(i
-1) % 2][j] + d[i % 2][j
-1];
第一次妄圖小陣列溜過去然後華麗麗re,改大之後開始tle
第二次進行了各種卡常跪著走結果仍然慘遭tle,直到應用了滾動陣列才過去。。。
而且空間優化效果顯著
礦工配餐 bzoj上的才行
題解luogu題目,可以滾動陣列,看題解的話是第三題
題解
滾動陣列詳解
滾動陣列 可以想象成顯示屏,對於有很多的數字來說,每次只顯示有限的數字,用完 顯示完 就向後移動一位,顯示的數量不變,但是在卡記憶體比較緊的題中,可以節省很多空間。最典型的就是斐波那契數列,普通的求解方法不外乎就是用遞推式f i f i 1 f i 2 但是這個如果資料量大的話會爆記憶體,而用滾動陣...
Top Secret Task dp 滾動陣列
傳送門 題目 dp i j k 表示 考慮到第i個數 計算前j個數的和 進行了k次操作 則有若不把第i個數放入前j個數中 dp i j k dp i 1 j k 若把第i個數放入前j個數中 至少需要把第i個移到第j個,即進行i j次操作 if k i j dp i j k dp i 1 j 1 k ...
打家劫舍(滾動陣列)
滾動陣列是dp中的一種程式設計思想。簡單的理解就是讓陣列滾動起來,每次都使用固定的幾個儲存空間,來達到壓縮,節省儲存空間的作用。比如斐波那契額數列 d 0 1 d 1 1 for i 2 i 80 i d i d i 1 d i 2 你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,...