مسألة السعة القصوى
بمعطى مصفوفة ، يمثّل كل عنصر فيها ارتفاع حاجز عمودي. ويمكن لأي حاجزين في المصفوفة، مع المساحة بينهما، أن يشكّلا حاوية.
تساوي سعة الحاوية حاصل ضرب ارتفاعها في عرضها (أي مساحتها)، حيث يتحدد الارتفاع بالحاجز الأقصر، ويكون العرض الفرق بين فهرسي الحاجزين في المصفوفة.
اختر حاجزين في المصفوفة بحيث تصبح سعة الحاوية الناتجة أقصى ما يمكن، وأعِد تلك السعة القصوى. ويوضح الشكل أدناه مثالاً على ذلك.

تتكوّن الحاوية من أي حاجزين، لذا فإن حالة هذه المسألة هي فهرسا الحاجزين، ويرمز إليهما بـ.
وفقاً لنص المسألة، تساوي السعة الارتفاع مضروباً في العرض، حيث يتحدد الارتفاع بالحاجز الأقصر، ويكون العرض الفرق بين فهرسي الحاجزين في المصفوفة. ولتكن السعة ؛ فنحصل على الصيغة التالية:
وليكن طول المصفوفة . عندئذٍ يكون عدد طرق اختيار حاجزين (أي العدد الإجمالي للحالات) . والطريقة الأكثر مباشرة هي استنفاد جميع الحالات تعدداً للعثور على السعة القصوى، ويكون التعقيد الزمني لها .
تحديد الاستراتيجية الجشعة
لهذه المسألة حل أكثر كفاءة. وكما هو موضح في الشكل أدناه، خذ حالة يكون فيها و. وفي هذه الحالة يكون هو الحاجز الأقصر و هو الحاجز الأطول.

وكما هو موضح في الشكل أدناه، إذا حرّكنا الآن الحاجز الأطول إلى الداخل نحو الحاجز الأقصر ، فستنقص السعة حتماً.
ويعود السبب إلى أنه بعد تحريك الحاجز الأطول ، ينقص العرض حتماً. وبما أن الارتفاع يتحدد بالحاجز الأقصر، فلا يمكن للارتفاع إلا أن يبقى كما هو ( يظل الحاجز الأقصر) أو أن ينقص ( يصبح الحاجز الأقصر بعد التحريك).

وعلى العكس، لا يمكن للسعة أن تزداد إلا بتحريك الحاجز الأقصر إلى الداخل. فرغم أن العرض سينقص حتماً، فإن الارتفاع قد يزداد (قد يكون الحاجز المنقول عند أطول). فمثلاً في الشكل أدناه، تزداد المساحة بعد تحريك الحاجز الأقصر.

ومن هذا نستنتج الاستراتيجية الجشعة لهذه المسألة: هيّئ مؤشرين عند الطرفين، وحرّك في كل جولة المؤشر المقابل للحاجز الأقصر إلى الداخل حتى يلتقي المؤشران.
يوضح الشكل أدناه عملية تنفيذ الاستراتيجية الجشعة.
- في الحالة الابتدائية، يكون المؤشران و عند طرفي المصفوفة.
- احسب سعة الحالة الحالية ، وحدّث السعة القصوى.
- قارن ارتفاعي الحاجزين و، وحرّك المؤشر المقابل للحاجز الأقصر إلى الداخل موضعاً واحداً.
- كرّر الخطوتين
2.و3.حتى يلتقي و.
تنفيذ الشيفرة
تعمل الشيفرة جولة على الأكثر، لذا فإن التعقيد الزمني هو .
لا تستخدم المتغيرات و و سوى مقدار ثابت من المساحة الإضافية، لذا فإن التعقيد المكاني هو .
Go
/* السعة القصوى: الخوارزمية الجشعة */
func maxCapacity(ht []int) int {
// هيّئ i وj عند طرفي المصفوفة
i, j := 0, len(ht)-1
// السعة القصوى الابتدائية هي 0
res := 0
// كرّر الاختيار الجشع حتى يلتقي الحاجزان
for i < j {
// حدّث السعة القصوى
capacity := int(math.Min(float64(ht[i]), float64(ht[j]))) * (j - i)
res = int(math.Max(float64(res), float64(capacity)))
// حرّك الحاجز الأقصر إلى الداخل
if ht[i] < ht[j] {
i++
} else {
j--
}
}
return res
}
TypeScript
/* السعة القصوى: الخوارزمية الجشعة */
function maxCapacity(ht: number[]): number {
// هيّئ i وj عند طرفي المصفوفة
let i = 0,
j = ht.length - 1;
// السعة القصوى الابتدائية هي 0
let res = 0;
// كرّر الاختيار الجشع حتى يلتقي الحاجزان
while (i < j) {
// حدّث السعة القصوى
const cap: number = Math.min(ht[i], ht[j]) * (j - i);
res = Math.max(res, cap);
// حرّك الحاجز الأقصر إلى الداخل
if (ht[i] < ht[j]) {
i += 1;
} else {
j -= 1;
}
}
return res;
}
برهان الصحة
سبب كون الجشع أسرع من التعداد الشامل هو أن كل جولة اختيار جشع «تتخطى» بعض الحالات.
فمثلاً، في الحالة ، افترض أن هو الحاجز الأقصر و هو الحاجز الأطول. فإذا حرّكنا الحاجز الأقصر جشعاً إلى الداخل موضعاً واحداً، ستُتخطى الحالات الموضحة في الشكل أدناه. وهذا يعني أنه لم يعد في الإمكان فحص سعاتها لاحقاً.

وبنظرة أدق، نجد أن هذه الحالات المتخطّاة هي بالضبط الحالات الناتجة عن تحريك الحاجز الأطول إلى الداخل. وقد أثبتنا سابقاً أن تحريك الحاجز الأطول إلى الداخل ينقص السعة حتماً. لذلك لا يمكن أن تكون أي من الحالات المتخطّاة هي الحل الأمثل، فتخطيها لا يجعلنا نفوّت الحل الأمثل.
يبين التحليل أعلاه أن تحريك الحاجز الأقصر عملية «آمنة»، وأن الاستراتيجية الجشعة فعّالة.