📘 CodingMarble Learn

डायनामिक प्रोग्रामिंग (Dynamic Programming)

डायनामिक प्रोग्रामिंग (DP) बड़ी समस्या को हल करते समय हर छोटी उपसमस्या को केवल एक बार हल करके उत्तर सहेज लेती है। यह तब काम करती है जब उपसमस्याएँ दोहराती हों और बड़ा सबसे अच्छा उत्तर छोटे सबसे अच्छे उत्तरों से बने (इष्टतम उपसंरचना)। ऊपर से नीचे DP मेमोइज़ेशन है; नीचे से ऊपर DP तालिका भरती है। DP अक्सर घातांकी समय को बहुपद समय बना देती है।

🎬 कदम-दर-कदम कहानी

  1. fib(5) सीधे रिकर्शन से: हर डिब्बा दो छोटे डिब्बों को बुलाता है। पेड़ तेज़ी से बढ़ता है: छोटी संख्या के लिए भी 15 पुकारें।
  2. रंग देखिए: fib(3) दो बार और fib(2) तीन बार हल हो रहा है। वही छोटा प्रश्न दोहराता है। इन्हें अतिव्यापी उपसमस्याएँ कहते हैं।
  3. मेमोइज़ेशन: पहली बार कोई डिब्बा हल करते ही उत्तर तालिका में लिख लो। अगली बार सिर्फ़ पढ़ लो। दोहराती शाखाएँ ग़ायब: 15 पुकारें घटकर 9।
  4. नीचे से ऊपर (टेबुलेशन): सबसे छोटे खानों से शुरू करो और तालिका बाएँ से दाएँ भरो। हर खाना पिछले दो खानों का जोड़। रिकर्शन बिल्कुल नहीं।
  5. लालची (greedy) तरीक़ा सबसे बड़ा सिक्का पहले उठाता है: {1, 3, 4} से 6 के लिए 4 + 1 + 1 = 3 सिक्के। DP हर छोटी रक़म जाँचकर 3 + 3 = 2 सिक्के पाती है।
  6. आपकी बारी: n चुनिए और भरिए दबाइए। सीधे रिकर्शन की पुकारें और DP के क़दमों की तुलना कीजिए।

टिप: 3D दृश्य को घुमाने के लिए खींचें। ज़ूम के लिए दो उंगलियाँ इस्तेमाल करें।

🤔 आम शंकाएँ और उनके जवाब

फ़िबोनाची के लिए सीधा रिकर्शन इतना धीमा क्यों?

हर पुकार दो और पुकारें करती है, इसलिए पेड़ लगभग हर स्तर पर दोगुना होता है, जबकि ज़्यादातर डिब्बे दोहराव हैं।

कैसे पता चले कि उपसमस्याएँ दोहराती हैं?

छोटे इनपुट का पुकार-पेड़ बनाइए। अगर वही डिब्बा (वही इनपुट) एक से ज़्यादा बार दिखे, तो वे दोहराती हैं।

मेमो कहाँ रखा जाता है?

रिकर्सिव पुकारों के बाहर एक डिक्शनरी या ऐरे में, ताकि हर पुकार उसे पढ़ सके।

क्या टेबुलेशन और मेमोइज़ेशन एक ही हैं?

उत्तर और समय एक, क्रम अलग: मेमोइज़ेशन ऊपर से शुरू होकर रिकर्शन करता है, टेबुलेशन आधार स्थितियों से लूप में ऊपर जाता है।

लालची तेज़ है तो हमेशा वही क्यों नहीं?

लालची कभी चुनाव पर दोबारा नहीं सोचता, इसलिए ग़लत चुनाव पर अटक सकता है। DP हर रक़म के लिए हर विकल्प जाँचती है।

DP सच में कितनी तेज़ है?

fib(10) के लिए सीधा रिकर्शन 177 पुकारें करता है, DP को 11 क़दम चाहिए। आख़िरी क़दम में आज़माइए।

सीधा रिकर्शन धीमा क्यों हो सकता है

फ़िबोनाची नियम: fib(n) = fib(n − 1) + fib(n − 2), जहाँ fib(0) = 0 और fib(1) = 1। सीधे रिकर्शन में हर पुकार दो और पुकारें करती है। पुकारें लगभग 1.6n की तरह बढ़ती हैं: fib(30) के लिए दस लाख से ज़्यादा पुकारें। यह घातांकी समय है।

बर्बादी इसलिए कि वही उपसमस्या बार-बार हल होती है।

DP की दो शर्तें

  1. अतिव्यापी उपसमस्याएँ: वही छोटी समस्या कई बार आती है।
  2. इष्टतम उपसंरचना: बड़ी समस्या का सबसे अच्छा उत्तर छोटी समस्याओं के सबसे अच्छे उत्तरों से बनता है।

DP बनाने के क़दम: (1) अवस्था तय करो (तालिका का एक खाना क्या दर्शाता है), (2) पुनरावृत्ति संबंध लिखो (खाना छोटे खानों से कैसे बनता है), (3) आधार स्थितियाँ रखो, (4) भरने का क्रम चुनो, (5) उत्तर पढ़ो।

ऊपर से नीचे (मेमोइज़ेशन) और नीचे से ऊपर (टेबुलेशन)

मेमोइज़ेशन (ऊपर से नीचे)

रिकर्शन रखो पर उत्तर डिक्शनरी या ऐरे में याद रखो।

memo = {}
def fib(n):
    if n < 2:
        return n
    if n in memo:
        return memo[n]
    memo[n] = fib(n - 1) + fib(n - 2)
    return memo[n]

टेबुलेशन (नीचे से ऊपर)

लूप से सबसे छोटी स्थिति से ऊपर की ओर ऐरे भरो।

def fib(n):
    F = [0] * (n + 1)
    if n > 0: F[1] = 1
    for i in range(2, n + 1):
        F[i] = F[i - 1] + F[i - 2]
    return F[n]

दोनों घातांकी की जगह O(n) समय लेते हैं। टेबुलेशन में कॉल स्टैक नहीं, इसलिए ओवरफ़्लो नहीं। तालिका में सिर्फ़ आख़िरी दो मान रखकर मेमोरी O(1) भी हो सकती है।

अन्य प्रोग्रामिंग विधियाँ: लालची, बैकट्रैकिंग, विभाजन और विजय

DP से सिक्का समस्या

def min_coins(coins, amount):
    INF = float('inf')
    best = [0] + [INF] * amount
    for a in range(1, amount + 1):
        for c in coins:
            if c <= a and best[a - c] + 1 < best[a]:
                best[a] = best[a - c] + 1
    return best[amount]

समय O(रक़म × सिक्कों की संख्या)।

करके देखिए: सीढ़ी के रास्ते गिनिए

आप सीढ़ी पर एक बार में 1 या 2 सीढ़ी चढ़ते हैं। सीढ़ी 6 तक कितने तरीक़े? तालिका बनाइए: ways[0] = 1, ways[1] = 1, ways[i] = ways[i − 1] + ways[i − 2]। काग़ज़ पर भरिए (उत्तर: 13)। यह फिर फ़िबोनाची पैटर्न है। 3D के आख़िरी क़दम में तालिका भरकर जाँचिए, फिर पायथन में लिखिए।

मुख्य सूत्र और परिभाषाएँ

हल किए गए उदाहरण

1. फ़िबोनाची के लिए F[0..7] तालिका भरिए।

0, 1, 1, 2, 3, 5, 8, 13। हर मान पिछले दो का जोड़।

2. fib(5) के लिए सीधा रिकर्शन कितनी पुकारें करता है?

Calls(0) = Calls(1) = 1। Calls(2) = 3, Calls(3) = 5, Calls(4) = 9, Calls(5) = 1 + 9 + 5 = 15।

3. मेमोइज़ेशन के साथ fib(5) की पुकारें?

5 से 2 तक हर n पहली बार 2 पुकारें करता है; कुल 2 × 5 − 1 = 9।

4. DP से {1, 3, 4} सिक्कों से 6 के लिए सबसे कम सिक्के।

best[0..6] = 0, 1, 2, 1, 1, 2, 2। best[6] = 1 + min(best[5], best[3], best[2]) = 1 + 1 = 2 (3 + 3)।

5. सीढ़ी: 1 या 2 क़दम, सीढ़ी 5 तक कितने तरीक़े?

सीढ़ी 0..5 के लिए ways = 1, 1, 2, 3, 5, 8, इसलिए 8 तरीक़े।

6. ग्रिड रास्ते: 3 × 3 खानों की ग्रिड में केवल दाएँ या नीचे चलकर कोने से कोने तक कितने रास्ते?

paths[i][j] = paths[i−1][j] + paths[i][j−1], पहली पंक्ति और स्तंभ = 1। पंक्तियाँ: 1 1 1 / 1 2 3 / 1 3 6। उत्तर 6।

आम गलतियाँ

अभ्यास क्विज़

1. DP तब उपयोगी है जब उपसमस्याएँ हों:
2. मेमोइज़ेशन का अर्थ:
3. DP फ़िबोनाची का समय:
4. {1, 3, 4} से 6 के लिए लालची तरीक़ा कितने सिक्के लेता है?
5. कौन-सी विधि बंद गली मिलने पर क़दम वापस लेती है?

अभ्यास: खुद जवाब दो

अपना जवाब लिखो या चुनो, फिर जाँचें दबाओ। अटको तो संकेत देखो; जवाब देने के बाद पूरा हल दिखेगा।

अक्सर पूछे जाने वाले प्रश्न

आसान शब्दों में डायनामिक प्रोग्रामिंग क्या है?

समस्या को छोटी दोहराती समस्याओं में तोड़ना, हर एक को एक बार हल करना, उत्तर तालिका में सहेजना और फिर से उपयोग करना।

डायनामिक प्रोग्रामिंग और रिकर्शन में क्या अंतर है?

रिकर्शन फ़ंक्शन लिखने का तरीक़ा है जो ख़ुद को बुलाता है। DP एक रणनीति है जो उपसमस्याओं के उत्तर सहेजती है; उसे रिकर्शन (मेमोइज़ेशन) या लूप (टेबुलेशन) से लिख सकते हैं।

DP और विभाजन-विजय में क्या अंतर है?

दोनों समस्या बाँटते हैं। विभाजन-विजय में हिस्से स्वतंत्र हैं; DP में वे दोहराते हैं, इसलिए DP उत्तर सहेजकर काम बचाती है।

यह कहाँ पढ़ाया जाता है

रोमानियाClasa a XI-aProgramming methods
यूक्रेन11 класAlgorithms
रूस11 классAlgorithms and programming

पहले यह पढ़ें

आगे पढ़ें

इससे जुड़े पाठ

सभी कंप्यूटर विज्ञान पाठ