WEEK 4 • Dynamic Programming

Knapsack Problem

مشكلة الحقيبة

إيه هي مشكلة الـ Knapsack؟

🎒 الفكرة الأساسية

📖 تشبيه السفر

تخيل إنك مسافر ومعاك شنطة سعتها محدودة:

  • • كل حاجة ليها وزن وقيمة
  • • الشنطة تشيل وزن محدود بس
  • • عايز تاخد حاجات بـأعلى قيمة ممكنة

📊 أنواع الـ Knapsack

0/1 Knapsack

كل حاجة إما تاخدها كلها أو تسيبها

→ لازم DP

Fractional Knapsack

ممكن تاخد جزء من أي حاجة

→ Greedy بينفع!

مثال: شنطة سعتها 7 كجم

💻

Laptop

الوزن: 3kg

القيمة: $4000

🎸

Guitar

الوزن: 1kg

القيمة: $1500

🔊

Speaker

الوزن: 4kg

القيمة: $3000

📸

Camera

الوزن: 2kg

القيمة: $2500

الحل بـ DP

0/1 Knapsack - بناء جدول الحلول

📐 الفكرة:

نبني جدول: كل صف = حاجة، كل عمود = سعة (من 0 للـ max)

dp[i][w] = أعلى قيمة ممكنة باستخدام أول i حاجات وسعة w

0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0
💻3kg 0 0 0 4K 4K 4K 4K 4K
🎸1kg 0 1.5K 1.5K 4K 5.5K 5.5K 5.5K 5.5K
🔊4kg 0 1.5K 1.5K 4K 5.5K 5.5K 5.5K 7K
📸2kg 0 1.5K 2.5K 4K 5.5K 6.5K 8K 8K

✓ الإجابة: $8,000

اخد: 💻 Laptop (3kg, $4K) + 🎸 Guitar (1kg, $1.5K) + 📸 Camera (2kg, $2.5K) = 6kg

المعادلة

dp[i][w] =

if weight[i] > w: dp[i-1][w] // مش هينفع ناخدها

else: max( dp[i-1][w], value[i] + dp[i-1][w-weight[i]] )

dp[i-1][w]: ما تاخدش الحاجة دي (خد أحسن قيمة من غيرها)
value[i] + dp[i-1][w-weight[i]]: خد الحاجة دي + أحسن قيمة للسعة الفاضلة

Implementation

knapsack.js
function knapsack(weights, values, capacity) {
  const n = weights.length;
  const dp = Array(n + 1).fill(null)
    .map(() => Array(capacity + 1).fill(0));
  
  for (let i = 1; i <= n; i++) {
    for (let w = 1; w <= capacity; w++) {
      // Don't take item i
      dp[i][w] = dp[i - 1][w];
      
      // Take item i (if possible)
      if (weights[i - 1] <= w) {
        const take = values[i - 1] + 
          dp[i - 1][w - weights[i - 1]];
        dp[i][w] = Math.max(dp[i][w], take);
      }
    }
  }
  
  return dp[n][capacity];
}

شرح الكود 📖

سطر 3-4: بنعمل جدول 2D مليان أصفار
سطر 6-7: نلف على كل الحاجات وكل السعات
سطر 9: Option 1: ما ناخدش الحاجة دي
سطر 12-16: Option 2: ناخدها لو ينفع، ونشوف أيهم أحسن

التعقيد

Time

O(n × W)

n: عدد الحاجات

W: السعة الكلية

Space

O(n × W)

للجدول 2D

ممكن يتحسن لـ O(W) بس!