تمارين
مراجعة المفاهيم
متى تكون البرمجة الديناميكية مناسبة؟
يقول أحد الطلاب: «كلما أمكن كتابة علاقة تعاودية، وجب استخدام البرمجة الديناميكية.»
لكل مهمة مما يلي، حدّد هل البرمجة الديناميكية أم التتبّع الرجعي أم حلقة أو صيغة رياضية دون جدول dp هي الأنسب. واذكر سبباً رئيسياً واحداً.
-
باستخدام فئات العملات
[1, 3, 4]، كوّن مبلغاً قدره 6 بأقل عدد من العملات. ويجوز استخدام كل فئة مراراً. -
أخرِج جميع تباديل
[1, 2, 3]. -
احسب .
وبالنسبة إلى المهمة التي تراها مناسبة للبرمجة الديناميكية، اذكر أيضاً ما يمثّله
dp[i].
الإجابة
-
البرمجة الديناميكية مناسبة. ليكُن
dp[i]أدنى عدد من العملات اللازمة لتكوين المبلغi. فلكل عملةcلا تتجاوزi، يكونdp[i-c] + 1إجابة مرشحة، ويُختار الحد الأدنى من هذه المرشحات. فالاختيارات المختلفة تصادف المبالغ نفسها مراراً، ويمكن بناء حل أمثل لمبلغ أكبر من حلول مثلى لمبالغ أصغر. وإجابة المبلغ 6 هي 2، باستخدام3 + 3. -
التتبّع الرجعي مناسب. تتطلب المهمة توليد التباديل الستة جميعها واحداً واحداً. ويستطيع التتبّع الرجعي اتخاذ اختيار بشكل منهجي، ومواصلة البحث، والتراجع عن الاختيار، ثم تجربة فرع آخر. وأياً كانت الطريقة، فإن إخراج كل تبديل فعلياً يقتضي تعديده.
-
تكفي حلقة أو صيغة المتتالية الحسابية. فرغم إمكان كتابة العلاقة التعاودية
S(i) = S(i-1) + i، فإن حسابS(i)يعتمد على قيمة أصغر واحدة فقط هيS(i-1). ولا يلزم حساب كل مجموع جزئي إلا مرة واحدة، فلا توجد مسائل فرعية مكررة ولا حاجة إلى جدولdp. و«إمكان كتابة علاقة تعاودية» لا يعني «الحاجة إلى البرمجة الديناميكية».
حساب خلية واحدة في جدول الحقيبة
لننظر في مسألة حقيبة 0-1 التالية: أوزان العناصر wgt = [1, 2, 3]، وقيمها val = [5, 11, 15]، وسعة الحقيبة 4.
وdp[i][c] هي أقصى قيمة يمكن الحصول عليها باستخدام أول من العناصر بحد سعة حقيبة ؛
ولا يلزم ملء الحقيبة بدقة.
احسب الحالة dp[3][4] فقط. والمعطى dp[2][4] = 16 وdp[2][1] = 5:
- إذا لم يُختَر العنصر الثالث، فما القيمة المرشحة؟
- إذا اختير العنصر الثالث، فكم تبقى من سعة، وما القيمة المرشحة؟
- كم ينبغي أن تكون
dp[3][4]؟ وأي العناصر يقابل اختيارها هذه القيمة؟
الإجابة
-
إذا لم يُختَر العنصر الثالث، فاحتفظ بالنتيجة الناتجة من العنصرين الأولين. والقيمة المرشحة هي
dp[2][4] = 16. -
وزن العنصر الثالث 3، لذا تبقى سعة بعد وضعه في الحقيبة. والقيمة المرشحة هي
dp[2][1] + 15 = 5 + 15 = 20. -
بمقارنة 16 و20 نحصل على
dp[3][4] = 20. وهذا يقابل اختيار العنصرين الأول والثالث، اللذين يساوي وزنهما الإجمالي وقيمتهما الإجمالية .ويوضح حساب هذه الحالة مقارنة واحدة من نوع «الاختيار أو عدم الاختيار» في مسألة حقيبة 0-1.
بأي ترتيب ينبغي تحديث سعات الحقيبة؟
تحتوي مسألة حقيبة 0-1 على عنصر واحد فقط، وزنه 2 وقيمته 5، وسعة الحقيبة 4.
ويمكن اختيار العنصر مرة واحدة على الأكثر. والمصفوفة الأحادية البعد الأولية هي dp = [0, 0, 0, 0, 0].
يعالج أحد الطلاب العنصر بتحديث السعات من 2 إلى 4:
- بعد تحديث
dp[2]، تصبح قيمته 5. - بعد تحديث
dp[3]، تصبح قيمته 5 أيضاً. - عند تحديث
dp[4]، يستخدم الطالب قيمةdp[2]التي حصل عليها حديثاً، فينتجdp[4] = 10.
- هل
dp[4] = 10صحيحة؟ ولماذا أو لماذا لا؟ - بما أن كل عنصر يمكن اختياره مرة واحدة على الأكثر، فماذا ينبغي أن تكون
dp[4]؟ - عند معالجة كل عنصر، هل ينبغي تحديث السعات من الأكبر إلى الأصغر أم من الأصغر إلى الأكبر؟ وما المشكلة التي يتجنبها ذلك؟
الإجابة
-
النتيجة غير صحيحة. فقيمة 10 تكافئ وضع العنصر ذي القيمة 5 في الحقيبة مرتين، مما يخالف شرط اختيار كل عنصر مرة واحدة على الأكثر.
-
يمكن للحقيبة أن تحتوي هذا العنصر الواحد على الأكثر، لذا فإن القيمة الصحيحة لـ
dp[4]هي 5. -
ينبغي تحديث السعات من الأكبر إلى الأصغر، بالترتيب 4 ثم 3 ثم 2. وبذلك، عند حساب
dp[c]، تظل القيمة المقروءة منdp[c-2]ناتجة مما قبل معالجة العنصر الحالي، مما يمنع إعادة استخدام العنصر الحالي في الجولة نفسها.
تمارين برمجية
عدد طرق صعود الدرج
يتكوّن الدرج من n درجة. وكل حركة تصعد درجة واحدة أو درجتين، ويجب أن تنتهي بالضبط عند الدرجة n.
احسب عدد الطرق المتمايزة للوصول إلى القمة. افترض أن n >= 1؛ ولا تتمايز الطرق إلا بمتتالية حركات الدرجة الواحدة والدرجتين.
استخدم مصفوفة برمجة ديناميكية أحادية البعد. ولا تستخدم الآن تحسين المساحة الذي يحتفظ بحالتين فقط.
تلميحات
- يمكن للحركة الأخيرة إلى الدرجة i أن تغطي درجة واحدة أو درجتين فقط
- لذلك dp[i] = dp[i-1] + dp[i-2]
- عالج أولاً الحالتين n = 1 و n = 2، ثم املأ الجدول ابتداءً من الدرجة 3
LeetCode{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }
حقيبة 0-1
معطى مصفوفتان متساويتا الطول wgt وval. وللعنصر i وزن صحيح موجب wgt[i] وقيمة صحيحة غير سالبة val[i].
وسعة الحقيبة cap عدد صحيح غير سالب. ويمكن اختيار كل عنصر مرة واحدة على الأكثر. ابحث عن أقصى قيمة إجمالية يمكن وضعها في الحقيبة
دون تجاوز cap. استخدم البرمجة الديناميكية أحادية البعد.
تلميحات
- هيّئ مصفوفة dp طولها cap + 1، حيث dp[c] هي أقصى قيمة في حدود سعة c
- عند معالجة العنصر i، قارن dp[c] الذي لا يختاره بـ dp[c-wgt[i]] + val[i] الذي يختاره
- حدّث السعات من الأكبر إلى الأصغر لتجنّب اختيار العنصر الحالي مراراً في الجولة نفسها