150 likes | 272 Vues
Fib(n): if n <= 2 return 1 else return Fib(n-1) + Fib(n-2) זמן ריצה :. טור פיבונצ’י : 1 1 2 3 5 8 13 21 34 … הגדרה : בעיה : קלט : N פלט :. מספרי פיבונצ’י. גרסה מקורית Fib(n): if n <= 2 return 1 else return Fib(n-1) + Fib(n-2). Array F(1..N) = (0..0)
E N D
Fib(n): if n <= 2 return 1 else return Fib(n-1) + Fib(n-2) זמן ריצה: טור פיבונצ’י: 1 1 2 3 5 8 13 21 34 … הגדרה: בעיה: קלט: N פלט: מספרי פיבונצ’י
גרסה מקורית Fib(n): if n <= 2 return 1 else return Fib(n-1) + Fib(n-2) Array F(1..N) = (0..0) Fib(n): if n<= 2 return 1 if F(n)<>0 return F(n) else F(n)=Fib(n-1)+Fib(n-2) return F(n) Memoization
memoized גרסה Array F(1..N) = (0..0) Fib(n): if n<= 2 return 1 if F(n)<>0 return F(n) else F(n)=Fib(n-1)+Fib(n-2) return F(n) Fib(n): Array F(1..n) F(1)=F(2)=1 for i = 1..n F(i)=F(i-1)+F(i-2) return F(n) גרסת תכנות דינמי
קלט: סדרת מספרים X1 … Xn פלט: הסכום המקסימאלי שניתן לקבל מהסדרה מבלי לקחת שני אברים רצופים. דוגמה: 3 6 2 3 5 7 6 תשובה: 17 קבוצה מקסימאלית ללא רצף
פתרון רקורסיבי: MIS(k): הסכום המקסימאלי שניתן לקבל מהאברים 1… k. if k = 0 return 0 if k = 1 return X1 s1 = MIS(k-2) + Xk s2 = MIS(k-1) return max(s1,s2) קלט: סדרת מספרים X1 … Xn פלט: הסכום המקסימאלי שניתן לקבל מהסדרה מבלי לקחת שני אברים רצופים. דוגמה: 3 6 2 3 5 7 6 תשובה: 17 קבוצה מקסימאלית ללא רצף
אתחול: Array S[0…N] S[0] = 0 ; S[1] = X1 מציאת הסכום המקסימאלי: for k = 2 … N do S[k] = max: S[k-1] S[k-2] + Xk Output S[N] מציאת הקבוצה עצמה: j=N while j>0 do if S[j] = S[j-1] j = j-1 else print j j = j-2 פתרון תכנון דינמי
דוגמה: 12, 5, 7, 10, 8, 16 ; 27 פתרון: 12+7+8=27 קלט: A1 … An ; S פלט: אוסף אברים {Ai} שסכומם S (או שאין כזה ) בעיית התרמיל
קלט: A1 … An ; S פלט: האם יש אוסף אברים {Ai} שסכומם S Solve(A1…An , S): If S=0 return true If n=0 return false return Solve(A1…An-1 , S) OR Solve(A1…An-1 , S-An) אלגוריתם רקורסיבי = נוסחת הפתרון
פתרון בעיית ההכרעה: for i = 1 … n for j = 1 … S B[i,j] = B[i-1,j] OR B[i-1,j-Ai] הדפסת הקבוצה עצמה: for i = n … 1 if not B[i-1,S] print Ai S = S - Ai מערך עזר: Boolean Array B[0..n,0..S] [B[i,j מציין האם יש תת קבוצה של A1…Aiשסכומה j. אתחול: for all j>0: B[0,j] = false for all i: B[i,0] = true פתרון תכנות דינמי
הגדרה: מרחק העריכה בין x לy הינו המספר המינימאלי של פעולות: מחיקת אות הוספת אות הנדרשות ל”הפוך” את x לy דוגמה: 3=(שלום, שוב)ED שלום -> שום -> שובם -> שוב קלט: שתי מחרוזות x1 … xn ; y1 … ym פלט: “מרחק העריכה” בינן מרחק עריכה
ED(x1 … xn ; y1 … ym): if n=0 return m if m=0 return n if xn=ym return ED(x1 … xn-1 ; y1 … ym-1) else: return min: 1+ ED(x1 … xn ; y1 … ym-1) 1+ ED(x1 … xn-1 ; y1 … ym) משפט: נוסחה זו נכונה. הוכחה: באינדוקציה על m+n. צעד האינדוקציה: (נוסחת ED) <= (ED אמיתי) (ED אמיתי) => (נוסחת ED) נוסחת הפתרון
מציאת המרחק: For i = 1 … n For j = 1 … m if xi = yj D(i,j) = D(i-1,j-1) else D(i,j) = 1+min: D(i-1,j), D(i,j-1) מערך עזר: Array D(0…n,0…m) :יהיה D(i,j) ED(x1…xi; y1…yj) אתחול: For all j: D(0,j) = j For all i: D(i,0) = i אלגוריתם תכנות דינמי
מציאת הפעולות עצמן i=n ; j=m repeat if xi=yj i=i-1 ; j=j-1 else if D(i,j) = 1+D(i-1,j) print “delete xi” ; i = i-1 else print “insert yj” ; j = j-1 until i=0 and j=0
דוגמה: רקאבלקרשד רק אבל קר שד (רק אב ???) (רק אבל קרש ???) קלט: מחרוזת x1 … xn פלט: חלוקה של x לחלקים שכל אחד מהם מופיע במילון. (או שאין כזו) הנחה: נתונה פרצדורה WORD(s) הבודקת אם המלה s במילון. חלוקה למילים
for i=1…n for j = 1 … i if P(j-1)<>0 and WORD(xj…xi) P(i)=j ; break i=n while i>0 print P(i); i=P(i)-1 Array P(0…n) (P(i אומר איפה מתחילה המלה האחרונה בחלוקת x1…xi (אם אין כזו -- 0) אתחול: for all i<>0 P(i)=0 P(0) = “*” אלגוריתם