מבני נתונים ואלגוריתמים - מחברת קורס/מבחן סופי מועד א' סמסטר ב' 2007 - תשובות
מתוך ויקיספר, אוסף ספרי הלימוד והמדריכים החופשי.
תוכן עניינים |
[עריכה] שאלה 1
הפתרון דומה מאד להוכחת הטענה שעצים אדומים-שחורים הם לוגריתמיים. נניח שגובה העץ הוא
. מה מספר המפתחות הקטן ביותר היכול להיות בעץ? קל לראות שזה המספר המתקבל כאשר כל אחד מהצמתים הוא מסוג Bar. במצב זה, היות שעל פי הנתונים כל המסלולים משורש לעלה הם בעלי אותו אורך, נקבל שמספר המפתחות הוא לכל הפחות
. הפתרון, לכן, מתקבל על ידי פתירת אי-השוויון
:




[עריכה] שאלה 2
נניח שזהו הגרף המקורי:
נבנה גרף חדש כך. ראשית, נקח את צמתי הגרף
, ונשכפל אותם 3 פעמים, בקבוצות
,
, ו
. לכל צומת
בקבוצה
, יש צומת
ב
, וצומת
ב
. התרשים הבא מראה זאת.
כעת נוסיף גם קשתות:
- כל קשת בין
ל
(בגרף המקורי) - נמתח אותה בגרף החדש בין
ב
לבין הצומת המתאים ל
ב
. - כל קשת בין
ל
(בגרף המקורי) - נמתח אותה בגרף החדש בין הצומת המתאים ל
ב
לבין הצומת המתאים ל
ב
.התרשים הבא מראה זאת (רק חלק מהקשתות מצויירות).
בנוסף נמתח עוד שני סוגי קשתות:
- לכל צומת
ב
, נמתח קשת במחיר
בין
ב
לבין
ב
. - לכל צומת
ב
, נמתח קשת במחיר
בין
ב
לבין
ב
.(לא נצייר קשתות אלו מטעמי נוחות.)
נשים לב שאם כל הגרפים הנ"ל מיוצגים ב[[מבני נתונים ואלגוריתמים - מחברת קורס/#|]], אז סיבוכיות הבניה היא
.
המשפט הבא מסביר את חשיבות הגרף החדש.
|
משפט: מחיר המסלול הזול ביותר מ |
הוכחה: מבניית הגרף החדש, ברור שכל מסלול מ
ל
ב
בגרף החדש, מורכב משני חלקים:
- מסלול זהה לחלוטין למסלול מ
ל
בגרף המקורי. - מסלול בעלות 1 ל
ב
, אם החלק הראשון זוגי, ומסלול בעלות
, אם החלק הראשון אי-זוגי.
לכן, כל שנותר הוא להריץ את אלגוריתם Dijkstra.
קל לראות שהסיבוכיות הכוללת היא זו של אלגוריתם Dijkstra.
[עריכה] שאלה 3
כבר ראינו את נוסחת הנסיגה
. נשתמש בזאת כדי להוכיח את הטענה בשאלה באינדוקציה. נראה שקיים
כך שתמיד
.
הוכחה: (מעבר האינדוקציה) נניח שהטענה נכונה עד (כולל)
, ונראה שהיא נכונה גם ל
.
![\displaystyle T(n) = \sum_{i = 0}^{n - 1}[T(i) \cdot T(n - i - 1)] \ge](http://upload.wikimedia.org/math/c/c/4/cc4080636597966cb18542176dad19bf.png)
![\displaystyle \sum_{i = 0}^{n - 1}[c \cdot 2^i \cdot c \cdot 2 ^{n - i - 1}] =](http://upload.wikimedia.org/math/f/e/a/fead411180426acfd921a905c1845f3b.png)
![\displaystyle \frac{c^2}{2} \sum_{i = 0}^{n - 1}[2^n] =](http://upload.wikimedia.org/math/c/0/b/c0be4dbc131e1f4c08b3285c3486ebbc.png)

נפתור
, ונקבל
. עבור
, נקבל שמספיק שיתקיים
.
מבדיקת מספר העצים השונים, עולה שקיים
מתאים גם לבסיס האינדוקציה (המקרים
).
[עריכה] שאלה 4
ראשית נניח שהמערך Mממויין, או, לחלופין, נמיין אותו בעזרת מיון מיזוג בסיבוכיות
.
נגדיר כ
את מירב הרווח שאפשר להרוויח מפתיחת סניפים הלקוחים מתוך
הבתים הראשונים.
|
משפט: לפי הגדרת
|
הוכחה: (2) אם
, אז ברור שהפתרון הרווחי ביותר הוא זה שבו בוחרים את הבית הראשון (והיחידי האפשרי לבחירה). אם
, אז או שבוחרים את בית
, או שלא. במקרה הראשון, מרוויחים
מהבחירה בבית, אך לפניו אסור לבחור באף בית בעל מיקום שהפרשו מ
קטן מ
. במקרה השני, הרווח הוא בדיוק הרווח כשמותר לבחור מבין
הבתים הראשונים.
להלן פסוודו-קוד המממש נוסחה זו.
Max-Profit(M, P, k, i) 1 if i == 0 2 return 0 3 if i == 1 4 return P[1] 5 guess-without = Max-Profit(i - 1) 6 guess-with = P[i] 7 if m[i] > k 8 j = Find-Index(M, M[i] - k) 9 guess-with = guess-with + Max-Profit(M, P, k, j) 10 if guess-with > guess-without 11 return guess-with 12 else 13 return guess-without
חשוב רק לשים לב לקריאה לפונקציה Find-Index ב8. פונקציה זו מוצאת את האינדקס הגדול ביותר בMשקטן מM[i] - k. היות שMממויין, נוכל לעשות זאת על ידי שינוי קטן בחיפוש בינרי. נוסיף גם Memoization:
1 MP = Make-Array(n) 2 for i in [1, ..., n] 3 MP[i] = Nil Max-Profit(M, P, k, i) 1 if i == 0 2 return 0 3 if MP[i] != Nil 4 return MP[i] 5 if i == 1 6 MP[1] = P[1] 7 return P[1] 8 guess-without = Max-Profit(i - 1) 9 guess-with = P[i] 10 if m[i] > k 11 j = Find-Index(M, M[i] - k) 12 guess-with = guess-with + Max-Profit(M, P, k, j) 13 if guess-with > guess-without 14 MP[i] = guess-with 15 return guess-with 16 else 17 MP[i] = guess-without 18 return guess-without
כעת נוסיף גם את הדפסת האיברים:
1 MP = Make-Array(n) 2 Used = Make-Array(n) 3 for i in [1, ..., n] 4 MP[i] = Nil Max-Profit(M, P, k, i) 1 if i == 0 2 return 0 3 if MP[i] != Nil 4 return MP[i] 5 if i == 1 6 MP[1] = P[1] 7 Used[1] = True 8 return P[1] 9 guess-without = Max-Profit(i - 1) 10 guess-with = P[i] 11 if m[i] > k 12 j = Find-Index(M, M[i] - k) 13 guess-with = guess-with + Max-Profit(M, P, k, j) 14 if guess-with > guess-without 15 MP[i] = guess-with 16 Used[i] = True 17 return guess-with 18 else 19 MP[i] = guess-without 20 Used[i] = False 21 return guess-without
המערך Used מתאר האם השתמשנו באיבר ה
או לא. נשתמש בו ע"י קריאה לPrint-Nums(k, n), כאשר Print-Nums מוגדרת כך:
Print-Nums(k, i) 1 if i &lt 1 2 return 3 if Used[i] 4 j = Find-Index(M, M[i] - k) 5 Print-Nums(k, j) 6 else 7 Print-Nums(k, i - 1) 8 if Used[i] 9 Print(i)
נותר רק לנתח את הסיבוכיות.
השורה j ← Find-Index(M, M[i] - k)אורכת
. אם נגדיר כ
את זמן הקריאה לMax-Profit(M, P, k, i)בהנחה שכל קריאה רקורסיבית היא
, אז
, והסיבוכיות היא
. מצד שני, מיון המערך הוא
, ולכן נקבל
.
[עריכה] שאלה 5
ניצור שתי קבוצות. הקבוצה השמאלית,
תכיל בתחילה את כל הצמתים (כלומר
); הקבוצה הימנית,
, תהיה ריקה בתחילה (כלומר
).
נאמר שקשת כלשהי
שמחה אם
ו
שייכות לשתי קבוצות שונות. נגדיר כ
את קבוצת הקשתות היוצאות מ
, ונגדיר כ
את קבוצת הקשתות השמחות היוצאות מ
. לפי הגדרות אלו:
- בתחילה, אף קשת אינה שמחה. (
.) - אם לפחות חצי מהקשתות היוצאות מכל צומת שמחות, פתרנו את הבעיה. (אם
, אז פתרנו את הבעיה.)
כעת, כל עוד לא פתרנו את הבעיה, נפעל כדלהלן. נבחר שרירותית צומת כלשהו
מבין הצמתים שרוב קשתותיהם אינו שמח. נעביר את
לקבוצה השניה.
|
דוגמה: בתרשים הבא, |
המשפט הבא מראה שהתהליך הוא סופי.
|
משפט: בכל פעם שמעבירים צומת כלשהו |
לפני הוכחת משפט זה, הבה נבין מדוע הוא מראה שהתהליך סופי. המשפט טוען שכל עוד קיים צומת כלשהו
שרוב קשתותיו אינו שמח - העברת
לקבוצה השניה תגדיל את מספר הקשתות השמחות. מספר הקשתות השמחות מתחיל ב0, ויכול להגיע לכל היותר ל
.
כעת נוכיח את המשפט.
הוכחה: נניח שהשכנים של
בקבוצה שלו הם
, ושכניו בקבוצה השניה הם
. נשים לב שבהכרח
.
לאחר העברת
, מספר הקשתות השמחות גדל ב
.



.

. לכן נעביר את 