BiliBili, ACFun… And More!【遞歸算法】
題源:http://acm.uestc.edu.cn/#/problem/show/3
題解:
題意:播放一段視頻文件,有播放速度和緩沖速度兩種,因為作者的癖好,播放前要緩沖幾秒鐘(這段時間不計算在總時間內),如果當播放文件大小等於緩沖文件大小時,緩沖文件還沒有緩沖完,播放器會從頭開始,但緩沖繼續緩沖。
總結幾個關鍵點:
1.當需要重新播放的時候,已經緩沖的大小(這裏的性質等於開始播放前緩沖的大小),此時的情形類似最開始的情況,只是提前緩沖大小不一樣了。
2.當播放大小等於緩沖大小(這裏列一個方程),判斷緩沖大小是否大於等於總大小,否則重新播放。
根據關鍵點的信息,可以嗅出遞歸算法的味道,什麽是遞歸算法?
在數學中,遞歸是X0屬於A集合,f(X0) = f(f(X1)),X0等於在X1對應的因變量。外層需要內層運算的結果
在編程中,遞歸是函數自己調用自己,但有一個遞歸出口。函數調用實際上是在“棧”中進行,最先調用的函數在棧底。
網上扣一張圖能很形象理解遞歸(如有侵權立即刪除)
回歸正題:
設播放速度為X,緩沖速度為Y,提前播放的時間T,文件總大小Z,需要的時間t,重新播放前一刻的緩沖大小Size。
1.分兩種情況。
1)網速倍兒棒,一次都沒重新播放過
t = Z/X
滿足條件:緩沖速度Y大於等於播放速度X 或者 當要重新播放的時候,緩沖大小大於總大小
Y >= X || T/(X - Y) >= S/X
2)令人抓狂的情況,老是重新播放
t = t1 + t2 + t3 ... + tn;
tn = Size/(X-Y);//第N次遞歸的播放時間
遞歸相同式子:緩沖文件大小Size,調用自身函數時,緩沖文件大小變為Size/(X-Y)*X;
遞歸終止條件:緩沖文件大小大於等於總文件大小S:size / (X - Y)*X >= S
附上代碼:
//C code #include<stdio.h> #define M 1000 double Time(double size, int X, int Y, int S);//遞歸函數 int main() { int num,X[M],Y[M],S[M],T[M];//X playspeed播放速度,Y bufferspeed緩沖速度,S totalsize文件總大小 int i;//循環參數 scanf("%d", &num);//測試數目 for (i = 0; i < num; i++) { scanf("%d %d %d %d", &X[i], &Y[i],&T[i], &S[i]); } for (i = 0; i < num; i++) { if (X[i] <= Y[i] || T[i] / (double)(X[i] - Y[i]) >= S[i] / (double)X[i])//網速好 { printf("Case #%d: %.3f\n", i+1, S[i] / (double)X[i]); } else//辣雞網速 { printf("Case #%d: %.3f\n", i + 1, Time(T[i] * Y[i], X[i], Y[i], S[i])); } } return 0; } double Time(double size,int X,int Y,int S)//size是重新播放前一刻的緩沖文件大小,作為遞歸變量 { double t = 0; if (size / (X - Y)*X < S)//遞歸終止條件 { t = size / (X - Y) + Time(size / (X - Y)*X, X, Y, S); } else { t = S / (double)X; } return t; }
有什麽問題歡迎在留言區交流!
BiliBili, ACFun… And More!【遞歸算法】