مرحباً بالخوارزميات › الخوارزميات الجشعة 17 / 19 السابق التالي

مسألة القطع بأقصى حاصل ضرب

بمعطى عدد صحيح موجب nn، قطّعه إلى مجموع عددين صحيحين موجبين على الأقل، وأوجد أكبر حاصل ضرب للأعداد الناتجة، كما يوضح الشكل أدناه.

تعريف مسألة القطع بأقصى حاصل ضرب

لنفترض أننا قطّعنا nn إلى mm من العوامل الصحيحة، حيث يُرمز إلى العامل رقم ii بـnin_i، أي

n=∑i=1mni n = \sum_{i=1}^{m}n_i

هدف هذه المسألة هو إيجاد أكبر حاصل ضرب لجميع العوامل الصحيحة، أي

max⁡(∏i=1mni) \max(\prod_{i=1}^{m}n_i)

نحتاج إلى تحديد عدد الأجزاء mm وما ينبغي أن تكون عليه كل nin_i.

تحديد الاستراتيجية الجشعة

كقاعدة عامة، كثيراً ما يكون حاصل ضرب عددين أكبر من مجموعهما. لنفترض أننا قطعنا عاملاً قدره 22 من nn؛ فيكون حاصل الضرب الناتج 2(n−2)2(n-2). ولنقارن هذا الحاصل مع nn:

2(n−2)≥n2n−n−4≥0n≥4 \begin{aligned} 2(n-2) & \geq n \newline 2n - n - 4 & \geq 0 \newline n & \geq 4 \end{aligned}

كما يوضح الشكل أدناه، عندما n≥4n \geq 4، فإن اقتطاع 22 سيزيد حاصل الضرب، وهذا يدل على أن الأعداد الصحيحة الأكبر من أو التي تساوي 44 ينبغي أن تُقطَّع جميعها.

الاستراتيجية الجشعة الأولى: إذا احتوى مخطط القطع على عامل ≥4\geq 4، فينبغي تقطيعه أكثر. ويجب ألا يحتوي مخطط القطع النهائي إلا على العوامل 11 و22 و33.

القطع يؤدي إلى زيادة حاصل الضرب

بعد ذلك، لننظر في أي عامل هو الأفضل. بين العوامل الثلاثة 11 و22 و33، من الواضح أن 11 هو الأسوأ، لأن 1×(n−1)<n1 \times (n-1) < n يظل صحيحاً دائماً، أي أن اقتطاع 11 سيقلل حاصل الضرب فعلاً.

كما يوضح الشكل أدناه، عندما n=6n = 6، لدينا 3×3>2×2×23 \times 3 > 2 \times 2 \times 2. وهذا يعني أن اقتطاع 33 أفضل من اقتطاع 22.

الاستراتيجية الجشعة الثانية: ينبغي ألا يحتوي مخطط القطع على أكثر من عاملي 22، لأن ثلاثة عوامل من 22 يمكن دائماً استبدالها بعاملين من 33 للحصول على حاصل ضرب أكبر.

عامل القطع الأمثل

وخلاصة القول، يمكن اشتقاق الاستراتيجيات الجشعة التالية.

  1. بمعطى عدد صحيح nn، اقطع العامل 33 باستمرار حتى يصبح الباقي 00 أو 11 أو 22.
  2. عندما يكون الباقي 00، فهذا يعني أن nn مضاعف للعدد 33، فلا حاجة إلى أي إجراء آخر.
  3. عندما يكون الباقي 22، لا تقطعه أكثر؛ اتركه كما هو.
  4. عندما يكون الباقي 11، بما أن 2×2>1×32 \times 2 > 1 \times 3، استبدل آخر 33 والباقي 11 بعاملين من 22.

تنفيذ الشيفرة

كما يوضح الشكل أدناه، لا نحتاج إلى حلقات لتقطيع العدد. بل نستخدم القسمة الصحيحة للحصول على عدد العوامل 33، ويُرمز إليه بـaa، ونستخدم عملية باقي القسمة للحصول على الباقي bb، فنحصل على:

n=3a+b n = 3 a + b

يرجى ملاحظة أنه في الحالة الحدية n≤3n \leq 3، يجب اقتطاع 11، ليكون حاصل الضرب 1×(n−1)1 \times (n - 1).

Go

/* مسألة القطع بأقصى حاصل ضرب: خوارزمية جشعة */
func maxProductCutting(n int) int {
	// عندما n <= 3، يجب قطع 1
	if n <= 3 {
		return 1 * (n - 1)
	}
	// اقطع 3 جشعاً، a هو عدد العوامل 3 وb هو الباقي
	a := n / 3
	b := n % 3
	if b == 1 {
		// عندما يكون الباقي 1، حوّل الزوج 1 * 3 إلى 2 * 2
		return int(math.Pow(3, float64(a-1))) * 2 * 2
	}
	if b == 2 {
		// عندما يكون الباقي 2، لا تفعل شيئاً
		return int(math.Pow(3, float64(a))) * 2
	}
	// عندما يكون الباقي 0، لا تفعل شيئاً
	return int(math.Pow(3, float64(a)))
}

TypeScript

/* مسألة القطع بأقصى حاصل ضرب: خوارزمية جشعة */
function maxProductCutting(n: number): number {
    // عندما n <= 3، يجب قطع 1
    if (n <= 3) {
        return 1 * (n - 1);
    }
    // اقطع 3 جشعاً، a هو عدد العوامل 3 وb هو الباقي
    let a: number = Math.floor(n / 3);
    let b: number = n % 3;
    if (b === 1) {
        // عندما يكون الباقي 1، حوّل الزوج 1 * 3 إلى 2 * 2
        return Math.pow(3, a - 1) * 2 * 2;
    }
    if (b === 2) {
        // عندما يكون الباقي 2، لا تفعل شيئاً
        return Math.pow(3, a) * 2;
    }
    // عندما يكون الباقي 0، لا تفعل شيئاً
    return Math.pow(3, a);
}

طريقة حساب مسألة القطع بأقصى حاصل ضرب

يعتمد التعقيد الزمني على كيفية تنفيذ الرفع إلى قوة في لغة البرمجة. وباتخاذ Python مثالاً، توجد ثلاث طرق شائعة لحساب القوى.

  • لكل من المعامل ** والدالة pow() تعقيد زمني O(log⁡⁡a)O(\log⁡ a).
  • تستدعي الدالة math.pow() داخلياً الدالة pow() من مكتبة C، وهي تنفذ الرفع إلى قوة للأعداد العائمة، بتعقيد زمني O(1)O(1).

يستخدم المتغيران aa وbb مقداراً ثابتاً من المساحة الإضافية، لذا يكون التعقيد المكاني O(1)O(1).

إثبات الصحة

نستخدم البرهان بالتناقض، وننظر في الحالة n≥4n \geq 4 فقط.

  1. جميع العوامل ≤3\leq 3: لنفترض أن مخطط القطع الأمثل يتضمن عاملاً x≥4x \geq 4. فيمكن تقطيعه أكثر إلى 2(x−2)2(x-2) للحصول على حاصل ضرب أكبر (أو مساوٍ). وهذا يناقض الافتراض.
  2. مخطط القطع لا يحتوي على 11: لنفترض أن مخطط القطع الأمثل يتضمن عاملاً قدره 11. فيمكن دمجه في عامل آخر للحصول على حاصل ضرب أكبر. وهذا يناقض الافتراض.
  3. مخطط القطع يحتوي على عاملي 22 على الأكثر: لنفترض أن مخطط القطع الأمثل يتضمن ثلاثة عوامل من 22. فيمكن استبدالها بعاملين من 33، للحصول على حاصل ضرب أكبر. وهذا يناقض الافتراض.