מבני נתונים ואלגוריתמים - מחברת קורס/אלגוריתמים/תכנון דינאמי/תרגילים/תוצאה ב"לוח כפל"/תשובה
נגדיר כ את העלות הזולה ביותר לטיפול בקטע באורך .
משפט: נתונה על ידי נוסחת הנסיגה הבאה:
, אז .
, אז . |
הוכחה: #אם
, אז אין מה לחתוך; ההובלה תעלה
.
- אם
, אז או שלא חותכים את הקטע, או שכן. אם לא חותכים, עלות השבירה 0, ועלות
ההובלה
. אם חותכים בנקודה
, אז עלות הטיפול בחלק השמאלי תהיה , עפ"י ההגדרה,
, עלות השבירה היא כמובן
, ועלות הטיפול בחלק הימני תהיה, עפ"י ההגדרה,
. נותר לקחת מינימום על פני
, ולהחליט האם לחתוך או לא.
להלן פסוודו-קוד המממש את נוסחת הנסיגה.
Min-Cost(i)
1 if i == 1
2 return F(1)
3 guess-without = F(i)
4 guess-with = ∞
5 for j in [1, … i - 1]]
6 if guess-with > Min-Cost(j) + k + Min-Cost(i - j)
7 guess-with = Min-Cost(j) + k + Min-Cost(i - j)
8 if guess-with
נוסיף memoization (השינויים מודגשים כך).
Min-Cost(i)
1 '''if M[i] != Nil'''
2 '''return M[i]'''
1 if i == 1
2 '''M[1] = F(1)'''
3 return F(1)
4 guess-without = F(i)
5 guess-with = ∞
6 for j in [1, … i - 1]]
7 if guess-with > Min-Cost(j) + k + Min-Cost(i - j)
8 guess-with = Min-Cost(j) + k + Min-Cost(i - j)
9 if guess-with M[i] = guess-with
10 return guess-with
11 else
12 '''M[i] = guess-without'''
13 return guess-without
המערך הגלובלי
M
באורך
n
מאותחל תחילה כולו ל
Nil
.
נוסיף גם מספיק מידע לצורך הדפסת פרטי הפתרון (השינויים מודגשים
כך).
Min-Cost(i)
1 if M[i] != Nil
2 return M[i]
1 if i == 1
2 M[1] = F(1)
3 '''Break[1] = Nil'''
4 return F(1)
5 guess-without = F(i)
6 guess-with = ∞
7 for j in [1, … i - 1]]
8 if guess-with > Min-Cost(j) + k + Min-Cost(i - j)
9 guess-with = Min-Cost(j) + k + Min-Cost(i - j)
10 '''if guess-with
11 '''Break[i] = j'''
12 if guess-with
13 return guess-with
14 else
15 M[i] = guess-without'''
16 return guess-without
המערך הגלובלי
Break
מכיל את ההחלטה שעשינו לגבי כל קטע.
Break[i]
הוא
Nil
אם החלטנו לא לחלק את הקטע, והוא
אם החלטנו לשבור בנקודה
j
.
כעת נדפיס את העצירות, ע"י קריאה ל
Print-Breaks(n, 0)
. הפונקציה מוגדרת להלן.
Print-Breaks(i, start)
1 if Break[i] == Nil
2 return
3 j = Break[i]
4 Print(j + start)
5 Print-Nums(j, start)
6 Print-Nums(i - j, start + j)
הפונקציה מקבלת שני ארגומנטים: אורך הקטע,
i
, ותחילת הקטע,
start
. נניח שהפונקציה נקראה עבור שני ערכים ספיציפיים כאלה. אם
{{{1}}}
, אז לא חתכנו את הקטע, ואין מה להדפיס. אם לא, ו
{{{1}}}
, אז יש להדפיס את הנקודה
j
(תוך זכירה שאנו נמצאים
start
מתחילת כל הגשר), את החלק השמאלי, ואת החלק הימני.
הסיבוכיות הנה
, וזאת מניתוח דומה מאד לזה שב
[[מבני נתונים ואלגוריתמים - מחברת קורס/#|]].