गतिक प्रोग्रामिंग

गतिशील प्रोग्रामिंग गणितीय अनुकूलन विधि और कंप्यूटर प्रोग्रामिंग विधि दोनों है। यह विधि 1950 के दशक में रिचर्ड बेलमैन द्वारा विकसित की गई थी और अंतरिक्ष इंजिनीयरिंग से लेकर अर्थशास्त्र तक कई क्षेत्रों में इसका उपयोग हुआ है।

दोनों संदर्भों में यह एक जटिल समस्या को पुनरावर्ती तरीके से सरल उप-समस्याओं में तोड़कर सरल बनाने के लिए संदर्भित करता है। जबकि कुछ निर्णय समस्याओं को इस तरह से अलग नहीं किया जा सकता है, ऐसे निर्णय जो समय में कई बिंदुओं को फैलाते हैं, अक्सर पुनरावर्ती रूप से अलग हो जाते हैं। इसी तरह, कंप्यूटर विज्ञान में, यदि किसी समस्या को उप-समस्याओं में तोड़कर और फिर पुनरावर्ती रूप से उप-समस्याओं का इष्टतम समाधान ढूंढकर हल किया जा सकता है, तो इसे 'इष्टतम उप-संरचना' कहा जाता है।

यदि उप-समस्याओं को पुनरावर्ती रूप से बड़ी समस्याओं के अंदर नेस्ट किया जा सकता है, ताकि गतिशील प्रोग्रामिंग विधियों को लागू किया जा सके, तो बड़ी समस्या के मान और उप-समस्याओं के मूल्यों के बीच संबंध होता है। अनुकूलन साहित्य में इस संबंध को बेलमैन समीकरण कहा जाता है।

गणितीय अनुकूलन
गणितीय अनुकूलन के संदर्भ में, गतिशील प्रोग्रामिंग आमतौर पर समय के साथ निर्णय चरणों के अनुक्रम में इसे तोड़कर निर्णय को सरल बनाने के लिए संदर्भित करता है। यह मूल्य कार्यों 'वी' के अनुक्रम को परिभाषित करके किया जाता है1, में2, ..., मेंn y को 1 से n तक के समय में सिस्टम के 'अवस्था चर' का प्रतिनिधित्व करने वाले एक तर्क के रूप में लेना। वी. की परिभाषाn(y) अंतिम समय पर स्थिति y में प्राप्त मान है। मान वीi पहले के समय में i = n −1, n − 2, ..., 2, 1 को बेलमैन समीकरण नामक पुनरावर्तन संबंध का उपयोग करके पीछे की ओर काम करके पाया जा सकता है। आई = 2, ..., एन, वी के लिएi&minus;1 किसी भी अवस्था में y की गणना V से की जाती हैi समय i − 1 और फ़ंक्शन V पर किसी निर्णय से लाभ के एक साधारण फ़ंक्शन (आमतौर पर योग) को अधिकतम करकेi यदि यह निर्णय किया जाता है तो सिस्टम की नई स्थिति में। चूंकि वीi पहले से ही आवश्यक राज्यों के लिए गणना की जा चुकी है, उपरोक्त ऑपरेशन उपज वीi&minus;1 उन राज्यों के लिए। अंत में, वी1 सिस्टम की प्रारंभिक अवस्था में इष्टतम समाधान का मूल्य है। पहले से की गई गणनाओं को वापस ट्रैक करके, निर्णय चर के इष्टतम मूल्यों को एक-एक करके पुनर्प्राप्त किया जा सकता है।

नियंत्रण सिद्धांत
नियंत्रण सिद्धांत में, स्वीकार्य नियंत्रण खोजने के लिए एक सामान्य समस्या है $$\mathbf{u}^{\ast}$$ जो सिस्टम का कारण बनता है $$\dot{\mathbf{x}}(t) = \mathbf{g} \left( \mathbf{x}(t), \mathbf{u}(t), t \right)$$ एक स्वीकार्य प्रक्षेपवक्र का पालन करने के लिए $$\mathbf{x}^{\ast}$$ निरंतर समय अंतराल पर $$t_{0} \leq t \leq t_{1}$$ जो हानि समारोह को कम करता है
 * $$J = b \left( \mathbf{x}(t_{1}), t_{1} \right) + \int_{t_{0}}^{t_{1}} f \left( \mathbf{x}(t), \mathbf{u}(t), t \right) \mathrm{d} t$$ इस समस्या का समाधान इष्टतम नियंत्रण कानून या नीति है $$\mathbf{u}^{\ast} = h(\mathbf{x}(t), t)$$, जो एक इष्टतम प्रक्षेपवक्र पैदा करता है $$\mathbf{x}^{\ast}$$ और एक कॉस्ट-टू-गो फ़ंक्शन $$J^{\ast}$$. उत्तरार्द्ध गतिशील प्रोग्रामिंग के मौलिक समीकरण का पालन करता है:
 * $$- J_{t}^{\ast} = \min_{\mathbf{u}} \left\{ f \left( \mathbf{x}(t), \mathbf{u}(t), t \right) + J_{x}^{\ast \mathsf{T}} \mathbf{g} \left( \mathbf{x}(t), \mathbf{u}(t), t \right) \right\}$$

हैमिल्टन-जैकोबी-बेलमैन समीकरण के रूप में जाना जाने वाला एक आंशिक अंतर समीकरण, जिसमें $$J_{x}^{\ast} = \frac{\partial J^{\ast}}{\partial \mathbf{x}} = \left[ \frac{\partial J^{\ast}}{\partial x_{1}} ~ \frac{\partial J^{\ast}}{\partial x_{2}} ~ \dots ~ \frac{\partial J^{\ast}}{\partial x_{n}} \right]^{\mathsf{T}}$$ और $$J_{t}^{\ast} = \frac{\partial J^{\ast}}{\partial t}$$. एक पाता है कि कम करना $$\mathbf{u}$$ के अनुसार $$t$$, $$\mathbf{x}$$, और अज्ञात फ़ंक्शन $$J_{x}^{\ast}$$ और फिर परिणाम को हैमिल्टन-जैकोबी-बेलमैन समीकरण में स्थानापन्न करता है ताकि आंशिक अंतर समीकरण को सीमा शर्त के साथ हल किया जा सके $$J \left( t_{1} \right) = b \left( \mathbf{x}(t_{1}), t_{1} \right)$$. व्यवहार में, सटीक अनुकूलन संबंध के लिए कुछ असतत सन्निकटन के लिए आमतौर पर संख्यात्मक आंशिक अंतर समीकरणों की आवश्यकता होती है।

वैकल्पिक रूप से, निरंतर प्रक्रिया को एक असतत प्रणाली द्वारा अनुमानित किया जा सकता है, जो हैमिल्टन-जैकोबी-बेलमैन समीकरण के अनुरूप निम्नलिखित पुनरावृत्ति संबंध की ओर जाता है:
 * $$J_{k}^{\ast} \left( \mathbf{x}_{n-k} \right) = \min_{\mathbf{u}_{n-k}} \left\{ \hat{f} \left( \mathbf{x}_{n-k}, \mathbf{u}_{n-k} \right) + J_{k-1}^{\ast} \left( \hat{\mathbf{g}} \left( \mathbf{x}_{n-k}, \mathbf{u}_{n-k} \right) \right) \right\}$$

पर $$k$$-वाँ चरण $$n$$ समान दूरी पर असतत समय अंतराल, और कहाँ $$\hat{f}$$ और $$\hat{\mathbf{g}}$$ असतत सन्निकटन को निरूपित करें $$f$$ और $$\mathbf{g}$$. इस कार्यात्मक समीकरण को बेलमैन समीकरण के रूप में जाना जाता है, जिसे अनुकूलन समीकरण के असतत सन्निकटन के सटीक समाधान के लिए हल किया जा सकता है।

अर्थशास्त्र से उदाहरण: रैमसे की इष्टतम बचत की समस्या
अर्थशास्त्र में, उद्देश्य आम तौर पर कुछ गतिशील सामाजिक कल्याण कार्य को अधिकतम (न्यूनतम करने के बजाय) करना है। रैमसे की समस्या में, यह फलन उपभोग की मात्रा को उपयोगिता के स्तरों से संबंधित करता है। ढीले ढंग से बोलते हुए, योजनाकार समसामयिक खपत और भविष्य की खपत (उत्पादन में उपयोग की जाने वाली भौतिक पूंजी में निवेश के माध्यम से) के बीच व्यापार-बंद का सामना करता है, जिसे अंतरकालिक पसंद के रूप में जाना जाता है। भविष्य की खपत को स्थिर दर पर छूट दी जाती है $$\beta \in (0,1)$$. पूंजी के संक्रमण समीकरण के लिए असतत सन्निकटन द्वारा दिया गया है
 * $$k_{t+1} = \hat{g} \left( k_{t}, c_{t} \right) = f(k_{t}) - c_{t}$$

कहाँ $$c$$ खपत है, $$k$$ पूंजी है, और $$f$$ इनडा स्थितियों को संतुष्ट करने वाला एक उत्पादन फलन है। एक प्रारंभिक पूंजी स्टॉक $$k_{0} > 0$$ ऐसा माना जाता है।

होने देना $$c_t$$ अवधि में खपत हो $t$, और मान लें कि उपभोग से उपयोगिता प्राप्त होती है $$u(c_t)=\ln(c_t)$$ जब तक उपभोक्ता रहता है। मान लें कि उपभोक्ता अधीर है, इसलिए वह भविष्य की उपयोगिता को एक कारक द्वारा छूट देता है $b$ प्रत्येक अवधि, जहां $$00$$, और मान लीजिए कि इस अवधि की पूंजी और खपत अगली अवधि की पूंजी के रूप में निर्धारित करती है $$k_{t+1}=Ak^a_t - c_t$$, कहाँ $A$ एक सकारात्मक स्थिरांक है और $$0<a<1$$. मान लें कि पूंजी नकारात्मक नहीं हो सकती। तब उपभोक्ता की निर्णय समस्या को इस प्रकार लिखा जा सकता है:


 * $$\max \sum_{t=0}^T b^t \ln(c_t)$$ का विषय है $$k_{t+1}=Ak^a_t - c_t \geq 0$$ सभी के लिए $$t=0,1,2,\ldots,T$$

इस तरह से लिखा गया, समस्या जटिल दिखती है, क्योंकि इसमें सभी विकल्प चरों को हल करना शामिल है $$c_0, c_1, c_2, \ldots, c_T$$. (राजधानी $$k_0$$ एक विकल्प चर नहीं है - उपभोक्ता की प्रारंभिक पूंजी दी गई है।)

इस समस्या को हल करने के लिए गतिशील प्रोग्रामिंग दृष्टिकोण में इसे छोटे निर्णयों के अनुक्रम में तोड़ना शामिल है। ऐसा करने के लिए, हम मूल्य कार्यों के अनुक्रम को परिभाषित करते हैं $$V_t(k)$$, के लिए $$t=0,1,2,\ldots,T,T+1$$ जो पूंजी की किसी भी राशि के होने के मूल्य का प्रतिनिधित्व करते हैं $k$ हर समय $t$. मृत्यु के बाद पूंजी होने से (धारणा के अनुसार) कोई उपयोगिता नहीं है, $$V_{T+1}(k)=0$$.

किसी भी समय पूंजी की किसी भी मात्रा के मूल्य की गणना बेलमैन समीकरण का उपयोग करके पीछे की ओर प्रेरण द्वारा की जा सकती है। इस समस्या में प्रत्येक के लिए $$t=0,1,2,\ldots,T$$, बेलमैन समीकरण है


 * $$V_t(k_t) \, = \, \max \left( \ln(c_t) + b V_{t+1}(k_{t+1}) \right)$$ का विषय है $$k_{t+1}=Ak^a_t - c_t \geq 0$$

यह समस्या हमारे द्वारा पहले लिखी गई समस्या से कहीं अधिक सरल है, क्योंकि इसमें केवल दो निर्णय चर शामिल हैं, $$c_t$$ और $$k_{t+1}$$. सहज रूप से, जन्म के समय अपनी संपूर्ण जीवन भर की योजना चुनने के बजाय, उपभोक्ता एक बार में एक कदम उठा सकता है। समय पर $t$, उनकी वर्तमान राजधानी $$k_t$$ दिया जाता है, और उसे केवल वर्तमान खपत चुनने की आवश्यकता होती है $$c_t$$ और बचत $$k_{t+1}$$.

वास्तव में इस समस्या को हल करने के लिए हम पीछे की ओर काम करते हैं। सरलता के लिए, पूँजी के वर्तमान स्तर को इस रूप में निरूपित किया जाता है $k$. $$V_{T+1}(k)$$ पहले से ही ज्ञात है, इसलिए एक बार बेलमैन समीकरण का उपयोग करके हम गणना कर सकते हैं $$V_T(k)$$, और इतने पर जब तक हम नहीं पहुंच जाते $$V_0(k)$$, जो पूरे जीवनकाल के लिए प्रारंभिक निर्णय समस्या का मूल्य है। दूसरे शब्दों में, एक बार हम जान जाते हैं $$V_{T-j+1}(k)$$, हम गणना कर सकते हैं $$V_{T-j}(k)$$, जो कि अधिकतम है $$\ln(c_{T-j}) + b V_{T-j+1}(Ak^a-c_{T-j})$$, कहाँ $$c_{T-j}$$ पसंद चर है और $$Ak^a-c_{T-j} \ge 0$$.

पीछे की ओर काम करते हुए, यह दिखाया जा सकता है कि मूल्य समय पर कार्य करता है $$t=T-j$$ है


 * $$V_{T-j}(k) \, = \, a \sum_{i=0}^j a^ib^i \ln k + v_{T-j}$$

जहां प्रत्येक $$v_{T-j}$$ एक स्थिर है, और समय पर उपभोग करने के लिए इष्टतम राशि है $$t=T-j$$ है


 * $$c_{T-j}(k) \, = \, \frac{1}{\sum_{i=0}^j a^ib^i} Ak^a$$

जिसे सरल बनाया जा सकता है


 * $$\begin{align}

c_{T}(k) & = Ak^a\\ c_{T-1}(k) & = \frac{Ak^a}{1+ab}\\ c_{T-2}(k) & = \frac{Ak^a}{1+ab+a^2b^2}\\ &\dots\\ c_2(k) & = \frac{Ak^a}{1+ab+a^2b^2+\ldots+a^{T-2}b^{T-2}}\\ c_1(k) & = \frac{Ak^a}{1+ab+a^2b^2+\ldots+a^{T-2}b^{T-2}+a^{T-1}b^{T-1}}\\ c_0(k) & = \frac{Ak^a}{1+ab+a^2b^2+\ldots+a^{T-2}b^{T-2}+a^{T-1}b^{T-1}+a^Tb^T} \end{align}$$ हम देखते हैं कि वर्तमान धन के एक बड़े हिस्से का उपभोग करना इष्टतम है क्योंकि एक वृद्ध हो जाता है, अंत में शेष सभी धन का उपभोग अवधि में होता है $T$, जीवन की अंतिम अवधि।

कंप्यूटर प्रोग्रामिंग
डायनेमिक प्रोग्रामिंग को लागू करने के लिए एक समस्या में दो प्रमुख विशेषताएँ होनी चाहिए: इष्टतम सबस्ट्रक्चर और अतिव्यापी उपसमस्या|ओवरलैपिंग सब-प्रोब्लम्स। यदि किसी समस्या को गैर-अतिव्यापी उप-समस्याओं के इष्टतम समाधानों के संयोजन से हल किया जा सकता है, तो रणनीति को विभाजित करें और जीतें एल्गोरिथम कहा जाता है। यही कारण है कि मर्ज़ सॉर्ट और जल्दी से सुलझाएं को डायनेमिक प्रोग्रामिंग समस्याओं के रूप में वर्गीकृत नहीं किया गया है।

इष्टतम उपसंरचना का अर्थ है कि किसी दी गई अनुकूलन समस्या का समाधान उसकी उप-समस्याओं के इष्टतम समाधानों के संयोजन से प्राप्त किया जा सकता है। इस तरह के इष्टतम अवसंरचनाओं को आमतौर पर पुनरावर्तन के माध्यम से वर्णित किया जाता है। उदाहरण के लिए, एक ग्राफ जी = (वी, ई) दिया गया है, सबसे छोटा पथ पी एक शीर्ष यू से एक शीर्ष वी तक इष्टतम उपसंरचना प्रदर्शित करता है: इस सबसे छोटे पथ पी पर किसी भी मध्यवर्ती शीर्ष डब्ल्यू को लें। यदि p वास्तव में सबसे छोटा पथ है, तो इसे उप-पथ p में विभाजित किया जा सकता है1यू से डब्ल्यू और पी2w से v तक ऐसे हैं कि, बदले में, ये वास्तव में संबंधित शीर्षों के बीच सबसे छोटा रास्ता हैं (एल्गोरिदम के परिचय में वर्णित सरल कट-एंड-पेस्ट तर्क द्वारा)। इसलिए, एक पुनरावर्ती तरीके से सबसे छोटा रास्ता खोजने के लिए आसानी से समाधान तैयार कर सकता है, जो कि बेलमैन-फोर्ड एल्गोरिथम या फ्लोयड-वॉर्शल एल्गोरिथम करता है।

अतिव्यापी उप-समस्याओं का अर्थ है कि उप-समस्याओं का स्थान छोटा होना चाहिए, अर्थात, समस्या को हल करने वाले किसी भी पुनरावर्ती एल्गोरिथ्म को नई उप-समस्याओं को उत्पन्न करने के बजाय समान उप-समस्याओं को बार-बार हल करना चाहिए। उदाहरण के लिए, फाइबोनैचि श्रृंखला उत्पन्न करने के लिए पुनरावर्ती सूत्रीकरण पर विचार करें: Fi = एफi&minus;1 + एफi&minus;2, बेस केस F के साथ1= एफ2= 1. फिर एफ43 = एफ42+ एफ41, और एफ42 = एफ41+ एफ40. अब एफ41 दोनों F के पुनरावर्ती उप-वृक्षों में हल किया जा रहा है43 साथ ही एफ42. भले ही उप-समस्याओं की कुल संख्या वास्तव में छोटी है (उनमें से केवल 43), यदि हम इस तरह के एक सरल पुनरावर्ती समाधान को अपनाते हैं, तो हम उन्हीं समस्याओं को बार-बार हल करते हैं। डायनेमिक प्रोग्रामिंग इस तथ्य को ध्यान में रखता है और प्रत्येक उप-समस्या को केवल एक बार हल करता है।

इसे दो तरीकों से प्राप्त किया जा सकता है:
 * टॉप-डाउन और बॉटम-अप डिज़ाइन | टॉप-डाउन दृष्टिकोण: यह किसी भी समस्या के पुनरावर्ती सूत्रीकरण का प्रत्यक्ष पतन है। यदि किसी समस्या का समाधान उसकी उप-समस्याओं के समाधान का उपयोग करके पुनरावर्ती रूप से तैयार किया जा सकता है, और यदि उसकी उप-समस्याएं अतिव्याप्त हैं, तो एक तालिका में उप-समस्याओं के समाधानों को आसानी से याद या संग्रहीत किया जा सकता है। जब भी हम एक नई उप-समस्या को हल करने का प्रयास करते हैं, तो हम पहले यह देखने के लिए तालिका की जांच करते हैं कि क्या यह पहले से ही हल हो गई है। यदि कोई समाधान दर्ज किया गया है, तो हम इसका सीधे उपयोग कर सकते हैं, अन्यथा हम उप-समस्या को हल करते हैं और तालिका में उसका समाधान जोड़ते हैं।
 * टॉप-डाउन और बॉटम-अप डिज़ाइन | बॉटम-अप दृष्टिकोण: एक बार जब हम किसी समस्या के समाधान को उसकी उप-समस्याओं के संदर्भ में पुनरावर्ती रूप से तैयार कर लेते हैं, तो हम समस्या को नीचे-ऊपर फैशन में सुधारने का प्रयास कर सकते हैं: उप को हल करने का प्रयास करें -समस्याएं पहले और उनके समाधान का निर्माण करने के लिए उपयोग करें और बड़ी उप-समस्याओं के समाधान पर पहुंचें। यह भी आम तौर पर छोटी उप-समस्याओं के समाधान का उपयोग करके बड़ी और बड़ी उप-समस्याओं के समाधान उत्पन्न करके एक सारणीबद्ध रूप में किया जाता है। उदाहरण के लिए, यदि हम पहले से ही F का मान जानते हैं41 और एफ40, हम सीधे F के मान की गणना कर सकते हैं42.

कॉल-बाय-नाम मूल्यांकन (इस तंत्र को कॉल-बाय-ज़रूरत के रूप में जाना जाता है) को गति देने के लिए, कुछ प्रोग्रामिंग लैंग्वेज स्वचालित रूप से तर्कों के एक विशेष सेट के साथ फ़ंक्शन कॉल के परिणाम को याद कर सकती हैं। कुछ भाषाएँ इसे पोर्टेबल रूप से संभव बनाती हैं (जैसे स्कीम (प्रोग्रामिंग लैंग्वेज), सामान्य लिस्प, पर्ल या डी ([[प्रोग्रामिंग भाषा)]])। कुछ भाषाओं में स्वचालित संस्मरण होता है बिल्ट इन, जैसे कि टेबल्ड प्रोलॉग और जे (प्रोग्रामिंग लैंग्वेज), जो एम क्रिया विशेषण के साथ संस्मरण का समर्थन करता है। किसी भी मामले में, यह केवल संदर्भित पारदर्शी कार्य के लिए ही संभव है। शब्द-पुनर्लेखन आधारित भाषाओं जैसे वोल्फ्राम भाषा के भीतर मेमोइज़ेशन को आसानी से सुलभ डिज़ाइन पैटर्न के रूप में भी देखा जाता है।

जैव सूचना विज्ञान
अनुक्रम संरेखण, प्रोटीन तह, आरएनए संरचना भविष्यवाणी और प्रोटीन-डीएनए बंधन जैसे कार्यों के लिए जैव सूचना विज्ञान में गतिशील प्रोग्रामिंग का व्यापक रूप से उपयोग किया जाता है। प्रोटीन-डीएनए बाइंडिंग के लिए पहला गतिशील प्रोग्रामिंग एल्गोरिदम 1970 के दशक में संयुक्त राज्य अमेरिका में चार्ल्स डेलीसी द्वारा स्वतंत्र रूप से विकसित किया गया था। और यूएसएसआर में जॉर्जी गुरस्की और अलेक्जेंडर ज़सेदातेलेव। हाल ही में ये एल्गोरिदम जैव सूचना विज्ञान और कम्प्यूटेशनल बायोलॉजी विज्ञान में बहुत लोकप्रिय हो गए हैं, विशेष रूप से न्यूक्लियोसोम पोजिशनिंग और प्रतिलेखन कारक बाइंडिंग के अध्ययन में।

सबसे छोटी पथ समस्या के लिए दिज्क्स्ट्रा का एल्गोरिथ्म
एक गतिशील प्रोग्रामिंग दृष्टिकोण से, सबसे छोटी पथ समस्या के लिए दिज्क्स्ट्रा का एल्गोरिथ्म एक क्रमिक सन्निकटन योजना है जो रीचिंग विधि द्वारा सबसे छोटी पथ समस्या के लिए गतिशील प्रोग्रामिंग कार्यात्मक समीकरण को हल करती है। 

वास्तव में, एल्गोरिथम के पीछे के तर्क की डिजस्ट्रा की व्याख्या, रेफरी> अर्थात् "Problem 2. Find the path of minimum total length between two given nodes $P$ and $Q$.

We use the fact that, if $R$ is a node on the minimal path from $P$ to $Q$, knowledge of the latter implies the knowledge of the minimal path from $P$ to $R$."

सबसे छोटी पथ समस्या के संदर्भ में रिचर्ड बेलमैन|बेलमैन के अनुकूलता के प्रसिद्ध सिद्धांत की व्याख्या है।

फाइबोनैचि अनुक्रम
फाइबोनैचि अनुक्रम के nवें सदस्य की गणना में गतिशील प्रोग्रामिंग का उपयोग करने से इसके प्रदर्शन में काफी सुधार होता है। यहाँ गणितीय परिभाषा पर सीधे आधारित एक भोली कार्यान्वयन है:

'फ़ंक्शन' फाइब (एन) 'अगर' एन <= 1 'वापसी' एन 'रिटर्न' फाइब (एन − 1) + फाइब (एन − 2)

ध्यान दें कि अगर हम फोन करते हैं, कहते हैं,, हम एक कॉल ट्री बनाते हैं जो फ़ंक्शन को एक ही मान पर कई अलग-अलग बार कॉल करता है:

विशेष रूप से,  स्क्रैच से तीन बार गणना की गई थी। बड़े उदाहरणों में, के कई और मान , या उप-समस्याओं की पुनर्गणना की जाती है, जिससे एक चरघातांकी समय एल्गोरिद्म तैयार होता है।

अब, मान लीजिए कि हमारे पास एक साधारण साहचर्य सरणी वस्तु है, m, जो प्रत्येक मान को मैप करता है  इसके परिणाम के लिए पहले से ही इसकी गणना की जा चुकी है, और हम इसका उपयोग करने और इसे अपडेट करने के लिए अपने कार्य को संशोधित करते हैं। परिणामी फ़ंक्शन को घातीय समय के बजाय केवल बिग-ओ नोटेशन (एन) समय की आवश्यकता होती है (लेकिन बिग-ओ नोटेशन (एन) स्पेस की आवश्यकता होती है):

'var' m := 'map'(0 → 0, 1 → 1) 'फ़ंक्शन' फाइब (एन) 'अगर कुंजी' एन 'मानचित्र में नहीं है' एम एम [एन]: = फाइब (एन - 1) + फाइब (एन - 2) 'वापसी' एम [एन]

मूल्यों को सहेजने की यह तकनीक जिसकी गणना पहले ही की जा चुकी है, मेमोइज़ेशन कहलाती है; यह टॉप-डाउन दृष्टिकोण है, क्योंकि हम पहले समस्या को उप-समस्याओं में तोड़ते हैं और फिर मूल्यों की गणना और संग्रह करते हैं।

बॉटम-अप दृष्टिकोण में, हम के छोटे मानों की गणना करते हैं  पहले, फिर उनसे बड़े मूल्य बनाएँ। यह विधि O(n) समय का भी उपयोग करती है क्योंकि इसमें एक लूप होता है जो n - 1 बार दोहराता है, लेकिन यह केवल स्थिर (O(1)) स्थान लेता है, शीर्ष-डाउन दृष्टिकोण के विपरीत जिसके लिए O(n) स्थान की आवश्यकता होती है नक्शा स्टोर करें।

'फ़ंक्शन' फाइब (एन) 'अगर' एन = 0 'वापसी' 0 'अन्य' 'var' पिछला फ़िब: = 0, करंट फ़िब: = 1 'दोहराना' n − 1 'बार' // n = 1 होने पर लूप को छोड़ दिया जाता है 'var' newFib := पिछलाFib + currentFib पिछलाफाइब := करेंटफाइब करेंटफाइब := newFib 'वापसी' करेंटFib

दोनों उदाहरणों में, हम केवल गणना करते हैं  एक बार, और फिर दोनों की गणना करने के लिए इसका उपयोग करें   और , इसकी गणना करने के बजाय हर बार उनमें से किसी एक का मूल्यांकन किया जाता है।

एक प्रकार का संतुलित 0–1 मैट्रिक्स
किसी की स्थिति के लिए, या तो शून्य या एक मान निर्दिष्ट करने की समस्या पर विचार करें $n &times; n$ मैट्रिक्स, के साथ $n$ यहां तक ​​कि, ताकि प्रत्येक पंक्ति और प्रत्येक कॉलम में बिल्कुल शामिल हो $n / 2$ शून्य और $n / 2$ वाले। हम पूछते हैं कि दिए गए के लिए कितने अलग-अलग कार्य हैं $$n$$. उदाहरण के लिए, कब $n = 4$, पांच संभावित समाधान हैं


 * $$\begin{bmatrix}

0 & 1 & 0 & 1 \\ 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 1 & 0 & 1 & 0 \end{bmatrix} \text{ and } \begin{bmatrix} 0 & 0 & 1 & 1 \\ 0 & 0 & 1 & 1 \\ 1 & 1 & 0 & 0 \\ 1 & 1 & 0 & 0 \end{bmatrix} \text{ and } \begin{bmatrix} 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 \\ 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 \end{bmatrix} \text{ and } \begin{bmatrix} 1 & 0 & 0 & 1 \\ 0 & 1 & 1 & 0 \\ 0 & 1 & 1 & 0 \\ 1 & 0 & 0 & 1 \end{bmatrix} \text{ and } \begin{bmatrix} 1 & 1 & 0 & 0 \\ 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 \\ 0 & 0 & 1 & 1 \end{bmatrix}.$$ कम से कम तीन संभावित दृष्टिकोण हैं: क्रूर-बल खोज, बैक ट्रैकिंग और डायनेमिक प्रोग्रामिंग।

क्रूर बल में शून्य और एक के सभी असाइनमेंट की जाँच करना और संतुलित पंक्तियों और स्तंभों की गणना करना शामिल है ($n / 2$ शून्य और $n / 2$ वाले)। जैसे वहां है $$2^{n^2}$$ संभावित कार्य और $$\tbinom{n}{n/2}^n$$ समझदार असाइनमेंट, यह रणनीति व्यावहारिक नहीं है सिवाय शायद तक $$n=6$$.

इस समस्या के लिए बैकट्रैकिंग में मैट्रिक्स तत्वों के कुछ क्रम को चुनना और पुनरावर्ती रूप से एक या शून्य को रखना शामिल है, जबकि यह जांचते हुए कि प्रत्येक पंक्ति और कॉलम में तत्वों की संख्या जिन्हें निर्दिष्ट नहीं किया गया है, साथ ही एक या शून्य की संख्या दोनों कम से कम हैं $n / 2$. क्रूर बल की तुलना में अधिक परिष्कृत होने के बावजूद, यह दृष्टिकोण हर समाधान पर एक बार जाएगा, जिससे यह अव्यवहारिक हो जाएगा $n$ छह से बड़ा, चूंकि समाधान की संख्या पहले से ही 116,963,796,250 है $n$= 8, जैसा कि हम देखेंगे।

डायनेमिक प्रोग्रामिंग उन सभी का दौरा किए बिना समाधानों की संख्या की गणना करना संभव बनाता है। पहली पंक्ति के लिए बैकट्रैकिंग मानों की कल्पना करें - प्रत्येक पहली पंक्ति मान के लिए प्राप्त समाधानों की सटीक गणना करने में सक्षम होने के लिए हमें शेष पंक्तियों के बारे में क्या जानकारी चाहिए? हमें विचार विमर्श करना है $k &times; n$ बोर्ड, कहाँ $1 &le; k &le; n$, किसका $$k$$ पंक्तियाँ होती हैं $$n/2$$ शून्य और $$n/2$$ वाले। फ़ंक्शन f जिस पर मेमोइज़ेशन लागू किया गया है, पूर्णांकों के n जोड़े के वैक्टर को स्वीकार्य बोर्डों (समाधान) की संख्या में मैप करता है। प्रत्येक कॉलम के लिए एक जोड़ी है, और इसके दो घटक क्रमशः शून्य की संख्या और उस कॉलम में अभी तक रखे जाने वाले लोगों को इंगित करते हैं। हम का मूल्य खोजते हैं $$ f((n/2, n/2), (n/2, n/2), \ldots (n/2, n/2)) $$ ($$n$$ तर्क या एक वेक्टर $$n$$ तत्व)। उप-समस्याओं के निर्माण की प्रक्रिया में प्रत्येक पर पुनरावृति शामिल है $$\tbinom{n}{n/2}$$ बोर्ड की शीर्ष पंक्ति के लिए संभावित असाइनमेंट, और प्रत्येक कॉलम के माध्यम से जाना, उस कॉलम के जोड़े के उपयुक्त तत्व से एक घटाना, इस पर निर्भर करता है कि शीर्ष पंक्ति के असाइनमेंट में शून्य है या उस स्थिति में एक है। यदि कोई एक परिणाम नकारात्मक है, तो असाइनमेंट अमान्य है और समाधान के सेट में योगदान नहीं करता है (पुनरावर्तन बंद हो जाता है)। अन्यथा, हमारे पास शीर्ष पंक्ति के लिए एक असाइनमेंट है $k &times; n$ बोर्ड और पुनरावर्ती रूप से शेष के समाधान की संख्या की गणना करें $( k &minus; 1) &times; n$ बोर्ड, शीर्ष पंक्ति के प्रत्येक स्वीकार्य असाइनमेंट के लिए समाधान की संख्या जोड़ना और योग वापस करना, जिसे याद किया जा रहा है। आधार मामला तुच्छ उपसमस्या है, जो a के लिए होता है $1 &times; n$ तख़्ता। इस बोर्ड के समाधान की संख्या या तो शून्य या एक है, यह इस बात पर निर्भर करता है कि सदिश किसका क्रमचय है $n / 2$ $$(0, 1)$$ और $n / 2$ $$(1, 0)$$ जोड़े हैं या नहीं।

उदाहरण के लिए ऊपर दिखाए गए पहले दो बोर्डों में सदिशों का क्रम होगा  ((2, 2) (2, 2) (2, 2) (2, 2)) ((2, 2) (2, 2) (2, 2) (2, 2)) के = 4 0 1 0 1 0 0 1 1

((1, 2) (2, 1) (1, 2) (2, 1)) ((1, 2) (1, 2) (2, 1) (2, 1)) के = 3 1 0 1 0 0 0 1 1

((1, 1) (1, 1) (1, 1) (1, 1)) ((0, 2) (0, 2) (2, 0) (2, 0)) के = 2 0 1 0 1 1 1 0 0

((0, 1) (1, 0) (0, 1) (1, 0)) ((0, 1) (0, 1) (1, 0) (1, 0)) k = 1 1 0 1 0 1 1 0 0

((0, 0) (0, 0) (0, 0) (0, 0)) ((0, 0) (0, 0), (0, 0) (0, 0)) 

समाधान की संख्या है


 * $$ 1,\, 2,\, 90,\, 297200,\, 116963796250,\, 6736218287430460752, \ldots $$

गतिशील प्रोग्रामिंग दृष्टिकोण के मैपल कार्यान्वयन के लिंक #बाहरी लिंक के बीच मिल सकते हैं।

चेकरबोर्ड
n × n वर्गों और एक लागत समारोह के साथ एक बिसात पर विचार करें  जो वर्ग से जुड़ी लागत लौटाता है   (  पंक्ति होने के नाते,   स्तंभ होना)। उदाहरण के लिए (5 × 5 बिसात पर),

इस प्रकार मान लें कि एक चेकर था जो पहली रैंक (यानी, पंक्ति) पर किसी भी वर्ग से शुरू हो सकता था और आप अंतिम रैंक तक पहुंचने के लिए सबसे छोटा रास्ता (प्रत्येक विज़िट की गई रैंक पर न्यूनतम लागत का योग) जानना चाहते थे; यह मानते हुए कि चेकर केवल तिरछे बाएँ आगे, तिरछे दाएँ आगे या सीधे आगे बढ़ सकता है। यानी चेकर ऑन  में जा सकते हैं ,   या. यह समस्या इष्टतम सबस्ट्रक्चर प्रदर्शित करती है। अर्थात्, संपूर्ण समस्या का समाधान उप-समस्याओं के समाधान पर निर्भर करता है। आइए एक फ़ंक्शन को परिभाषित करें  जैसा


 * q(i, j) = वर्ग (i, j) तक पहुँचने के लिए न्यूनतम लागत।

रैंक से शुरू  और रैंक पर उतरना , हम प्रत्येक क्रमिक रैंक पर सभी वर्गों के लिए इस फ़ंक्शन के मान की गणना करते हैं। प्रत्येक रैंक पर न्यूनतम मान रखने वाले वर्ग को चुनना हमें रैंक के बीच सबसे छोटा रास्ता देता है   और रैंक.

कार्यक्रम  इसके नीचे के तीन वर्गों में से किसी एक तक पहुंचने के लिए न्यूनतम लागत के बराबर है (चूंकि केवल वही वर्ग हैं जो इस तक पहुंच सकते हैं) प्लस. उदाहरण के लिए:


 * $$q(A) = \min(q(B),q(C),q(D))+c(A) \, $$

अब, परिभाषित करते हैं  कुछ अधिक सामान्य शब्दों में:


 * $$q(i,j)=\begin{cases} \infty & j < 1 \text{ or }j > n \\ c(i, j) & i = 1 \\ \min(q(i-1, j-1), q(i-1, j), q(i-1, j+1)) + c(i,j) & \text{otherwise.}\end{cases}$$

इस समीकरण की पहली पंक्ति एक बोर्ड से संबंधित है जिसे वर्गों के रूप में अनुक्रमित किया गया है  सबसे कम सीमा पर और   उच्चतम सीमा पर। दूसरी पंक्ति निर्दिष्ट करती है कि पहली रैंक पर क्या होता है; एक आधार मामला प्रदान करना। तीसरी पंक्ति, प्रत्यावर्तन, महत्वपूर्ण हिस्सा है। यह प्रतिनिधित्व करता है   उदाहरण में शर्तें। इस परिभाषा से हम सीधा पुनरावर्ती कोड प्राप्त कर सकते हैं. निम्नलिखित स्यूडोकोड में,  बोर्ड का आकार है,   लागत समारोह है, और   कम से कम कई मान लौटाता है:

फ़ंक्शन minCost(i, j)    यदि जे <1 या जे> एन वापसी अनंत और अगर मैं = 1 वापसी सी (मैं, जे) अन्य वापसी मिनट (minCost(i-1, j-1), minCost(i-1, j), minCost(i-1, j+1) ) + c(i, j)

यह फ़ंक्शन केवल पथ लागत की गणना करता है, वास्तविक पथ की नहीं। हम नीचे वास्तविक पथ पर चर्चा करते हैं। यह, फाइबोनैचि-संख्या उदाहरण की तरह, बहुत धीमा है क्योंकि यह अतिव्यापी उप-समस्या विशेषता को भी प्रदर्शित करता है। यही है, यह एक ही पथ लागत को बार-बार पुनर्गणना करता है। हालाँकि, यदि हम दो-आयामी सरणी में पथ लागतों को संग्रहीत करते हैं, तो हम इसे नीचे-ऊपर फैशन में बहुत तेज़ी से गणना कर सकते हैं  फ़ंक्शन का उपयोग करने के बजाय। यह पुनर्गणना से बचा जाता है; सरणी के लिए आवश्यक सभी मान   समय से पहले केवल एक बार गणना की जाती है। के लिए पूर्व-गणना मान   जरूरत पड़ने पर बस ऊपर देखा जाता है।

हमें यह भी जानने की जरूरत है कि वास्तविक सबसे छोटा रास्ता क्या है। ऐसा करने के लिए, हम एक और सरणी का उपयोग करते हैं ; एक पूर्ववर्ती सरणी। यह सरणी किसी भी वर्ग का पथ रिकॉर्ड करती है. के पूर्ववर्ती  इंडेक्स के सापेक्ष ऑफ़सेट के रूप में मॉडलिंग किया गया है (में  ) की पूर्व-गणना पथ लागत की. पूर्ण पथ का पुनर्निर्माण करने के लिए, हम इसके पूर्ववर्ती को देखते हैं, फिर उस वर्ग का पूर्ववर्ती, फिर उस वर्ग का पूर्ववर्ती, और इसी तरह पुनरावर्ती रूप से, जब तक कि हम प्रारंभिक वर्ग तक नहीं पहुंच जाते। निम्नलिखित स्यूडोकोड पर विचार करें:

फ़ंक्शन कंप्यूटशॉर्टेस्टपाथएरेज़ x के लिए 1 से n तक क्यू [1, एक्स] := सी (1, एक्स) वाई के लिए 1 से एन तक क्ष[य, 0] := अनंत क्यू [वाई, एन + 1] : = अनंत वाई के लिए 2 से एन तक x के लिए 1 से n तक एम : = मिनट (क्यू [वाई -1, एक्स -1], क्यू [वाई -1, एक्स], क्यू [वाई -1, एक्स + 1]) क्यू [वाई, एक्स]: = एम + सी (वाई, एक्स) अगर एम = क्यू [वाई -1, एक्स -1] पी [वाई, एक्स]: = -1 और अगर एम = क्यू [वाई -1, एक्स] पी [वाई, एक्स] : = 0 अन्य पी [वाई, एक्स] : = 1

अब शेष न्यूनतम खोजने और इसे प्रिंट करने का एक साधारण मामला है।

फ़ंक्शन गणना सबसे छोटा पथ कंप्यूटशॉर्टेस्टपाथअरे मिनइंडेक्स: = 1 मिनट := क्ष[एन, 1] मैं 2 से एन के लिए अगर क्यू [एन, मैं] <मिनट मिनइंडेक्स: = मैं मिनट : = क्यू [एन, मैं] प्रिंटपाथ (एन, मिनइंडेक्स)

फ़ंक्शन प्रिंटपाथ (वाई, एक्स) प्रिंट (एक्स) प्रिंट (<-) अगर वाई = 2 प्रिंट (एक्स + पी [वाई, एक्स]) अन्य प्रिंटपाथ (वाई -1, एक्स + पी [वाई, एक्स])

अनुक्रम संरेखण
आनुवंशिकी में, अनुक्रम संरेखण एक महत्वपूर्ण अनुप्रयोग है जहां गतिशील प्रोग्रामिंग आवश्यक है। आमतौर पर, समस्या में एक तत्व को बदलने, डालने या हटाने वाले संपादन कार्यों का उपयोग करके एक अनुक्रम को दूसरे में बदलना शामिल है। प्रत्येक ऑपरेशन की एक संबद्ध लागत होती है, और लक्ष्य संपादन दूरी का पता लगाना है।

समस्या को स्वाभाविक रूप से एक पुनरावर्तन के रूप में कहा जा सकता है, एक अनुक्रम A को अनुक्रम B में या तो बेहतर रूप से संपादित किया जाता है:


 * 1) बी के पहले अक्षर को सम्मिलित करना, और ए और बी की पूंछ का एक इष्टतम संरेखण करना
 * 2) ए के पहले अक्षर को हटाना, और ए और बी की पूंछ का इष्टतम संरेखण करना
 * 3) A के पहले अक्षर को B के पहले अक्षर से बदलना, और A और B की पूंछ के इष्टतम संरेखण का प्रदर्शन करना।

आंशिक संरेखण को एक मैट्रिक्स में सारणीबद्ध किया जा सकता है, जहां सेल (i,j) में A[1..i] से B[1..j] के इष्टतम संरेखण की लागत शामिल है। सेल (i, j) में लागत की गणना संबंधित संचालन की लागत को उसके पड़ोसी सेल की लागत में जोड़कर और इष्टतम का चयन करके की जा सकती है।

विभिन्न संस्करण मौजूद हैं, स्मिथ-वाटरमैन एल्गोरिथम और नीडलमैन-वुन्श एल्गोरिथम देखें।

हनोई पहेली का टॉवर
हनोई की मीनार या हनोई की मीनारें एक गणितीय खेल या पहेली है। इसमें तीन छड़ें और विभिन्न आकारों की कई डिस्क होती हैं जो किसी भी छड़ पर स्लाइड कर सकती हैं। पहेली एक छड़ पर आकार के आरोही क्रम में एक साफ ढेर में डिस्क के साथ शुरू होती है, जो शीर्ष पर सबसे छोटी होती है, इस प्रकार एक शंक्वाकार आकार बनाती है।

पहेली का उद्देश्य निम्नलिखित नियमों का पालन करते हुए पूरे ढेर को दूसरी छड़ पर ले जाना है:


 * एक समय में केवल एक ही डिस्क को चलाया जा सकता है।
 * प्रत्येक चाल में एक रॉड से ऊपरी डिस्क को लेना और दूसरी रॉड पर स्लाइड करना शामिल है, जो उस रॉड पर पहले से मौजूद अन्य डिस्क के ऊपर हो सकती है।
 * छोटी डिस्क के ऊपर कोई डिस्क नहीं रखी जा सकती है।

गतिशील प्रोग्रामिंग समाधान में बेलमैन समीकरण को हल करना शामिल है


 * एस (एन, एच, टी) = एस (एन-1, एच, नहीं (एच, टी)); एस (1, एच, टी); एस(एन-1,नहीं(एच,टी),टी)

जहाँ n स्थानांतरित होने वाली डिस्क की संख्या को दर्शाता है, h होम रॉड को दर्शाता है, t लक्ष्य रॉड को दर्शाता है, not(h,t) तीसरी रॉड को दर्शाता है (न तो h और न ही t), ; संयोजन को दर्शाता है, और


 * S(n, h, t) := n डिस्क वाली समस्या का समाधान जिसे रॉड h से रॉड t में ले जाना है।

n = 1 के लिए समस्या तुच्छ है, अर्थात् S (1, h, t) = एक डिस्क को रॉड h से रॉड t तक ले जाएँ (केवल एक डिस्क शेष है)।

इस समाधान के लिए आवश्यक चालों की संख्या 2 हैn − 1। यदि उद्देश्य चालों की संख्या को 'अधिकतम' करना है (बिना साइकिल चलाए) तो गतिशील प्रोग्रामिंग बेलमैन समीकरण थोड़ा अधिक जटिल है और 3n − 1 चालें आवश्यक हैं।

अंडे छोड़ने वाली पहेली
N = 2 अंडे और H = 36 मंजिलों वाली एक इमारत से जुड़ी इस प्रसिद्ध पहेली के उदाहरण का विवरण निम्नलिखित है: : मान लीजिए कि हम जानना चाहते हैं कि 36 मंजिला इमारत में कौन सी मंजिल अंडे छोड़ने के लिए सुरक्षित है, और कौन से अंडे लैंडिंग पर टूट जाएंगे (यू.एस. अंग्रेजी शब्दावली का उपयोग करते हुए, जिसमें पहली मंजिल जमीनी स्तर पर है)। हम कुछ धारणाएँ बनाते हैं:


 * जो अंडा गिरकर बच जाता है उसे फिर से इस्तेमाल किया जा सकता है।
 * टूटे हुए अंडे को फेंक देना चाहिए।
 * गिरने का प्रभाव सभी अंडों पर एक जैसा होता है।
 * अगर अंडा गिराने पर टूट जाता है तो ऊपर की खिड़की से गिराने पर टूट जाता है।
 * यदि अंडा गिरने से बच जाता है, तो वह कम गिरने से बचेगा।
 * इस बात से इंकार नहीं किया जाता है कि पहली मंजिल की खिड़कियां अंडे तोड़ती हैं, और न ही इस बात से इंकार किया जाता है कि अंडे 36 वीं मंजिल की खिड़कियों से बच सकते हैं।


 * यदि केवल एक अंडा उपलब्ध हो और हम सही परिणाम प्राप्त करना सुनिश्चित करना चाहते हैं, तो प्रयोग केवल एक ही तरीके से किया जा सकता है। पहली मंजिल की खिड़की से अंडा गिराओ; यदि यह बच जाता है, तो इसे दूसरी मंजिल की खिड़की से गिरा दें। ऊपर की ओर तब तक जारी रखें जब तक यह टूट न जाए। सबसे खराब स्थिति में, इस विधि में 36 बूंदों की आवश्यकता हो सकती है। मान लीजिए 2 अंडे उपलब्ध हैं। अंडे की बूंदों की सबसे कम संख्या क्या है जो सभी मामलों में काम करने की गारंटी देती है?

इस पहेली के लिए गतिशील प्रोग्रामिंग बेलमैन समीकरण प्राप्त करने के लिए, गतिशील प्रोग्रामिंग मॉडल की स्थिति को एक जोड़ी एस = (एन, के) होने दें, जहां


 * n = उपलब्ध परीक्षण अंडों की संख्या, n = 0, 1, 2, 3, ..., N − 1।
 * k = (लगातार) मंजिलों की संख्या जिनका अभी परीक्षण किया जाना है, k = 0, 1, 2, ..., H − 1।

उदाहरण के लिए, s = (2,6) इंगित करता है कि दो परीक्षण अंडे उपलब्ध हैं और 6 (लगातार) मंजिलों का परीक्षण किया जाना बाकी है। प्रक्रिया की प्रारंभिक अवस्था s = (N,H) है जहाँ N प्रयोग के प्रारंभ में उपलब्ध परीक्षण अंडों की संख्या को दर्शाता है। यह प्रक्रिया या तो समाप्त हो जाती है जब कोई और परीक्षण अंडे नहीं होते हैं (n = 0) या जब k = 0, जो भी पहले होता है। यदि समाप्ति स्थिति s = (0,k) और k > 0 पर होती है, तो परीक्षण विफल हो गया।

अब चलो


 * W(n,k) = सबसे खराब स्थिति के तहत महत्वपूर्ण मंजिल के मूल्य की पहचान करने के लिए आवश्यक परीक्षणों की न्यूनतम संख्या यह देखते हुए कि प्रक्रिया राज्य s' में है ' = (एन,के'')।

तभी यह दिखाया जा सकता है


 * W(n,k) = 1 + min{max(W(n − 1, x − 1), W(n,k − x)): x = 1, 2, ..., k }

W(n,0) = 0 सभी n > 0 के लिए और W(1,k) = k सभी k के लिए। n और k के मानों को व्यवस्थित रूप से बढ़ाकर इस समीकरण को पुनरावृत्त रूप से हल करना आसान है।

एक अलग पैरामीट्रिजेशन का उपयोग करके तेज़ डीपी समाधान
ध्यान दें कि उपरोक्त समाधान लेता है $$O( n k^2 )$$ डीपी समाधान के साथ समय। इसमें सुधार किया जा सकता है $$O( n k \log k )$$ इष्टतम पर द्विआधारी खोज द्वारा समय $$x$$ उपरोक्त पुनरावृत्ति में, चूंकि $$W(n-1,x-1)$$ में बढ़ रहा है $$x$$ जबकि $$W(n,k-x)$$ में घट रहा है $$x$$, इस प्रकार एक स्थानीय न्यूनतम $$\max(W(n-1,x-1),W(n,k-x))$$ एक वैश्विक न्यूनतम है। इसके अलावा, इष्टतम भंडारण करके $$x$$ डीपी तालिका में प्रत्येक सेल के लिए और पिछले सेल के लिए इसके मान का जिक्र करते हुए, इष्टतम $$x$$ प्रत्येक कोशिका के लिए निरंतर समय में पाया जा सकता है, इसे सुधारने के लिए $$O( n k )$$ समय। हालाँकि, एक और भी तेज़ समाधान है जिसमें समस्या का एक अलग पैरामीट्रिजेशन शामिल है:

होने देना $$k$$ मंजिलों की कुल संख्या इस प्रकार हो कि अंडे नीचे गिरने पर टूट जाएं $$k$$वीं मंजिल (उपरोक्त उदाहरण लेने के बराबर है $$k=37$$).

होने देना $$m$$ वह न्यूनतम मंजिल हो जिससे अंडे को तोड़ने के लिए गिराया जाना चाहिए।

होने देना $$f(t,n)$$ के मूल्यों की अधिकतम संख्या हो $$m$$ जिनका उपयोग करके पहचाना जा सकता है $$t$$ कोशिश करता है और $$n$$ अंडे।

तब $$f(t,0) = f(0,n) = 1$$ सभी के लिए $$t,n \geq 0$$.

होने देना $$a$$ वह मंजिल हो जहां से इष्टतम रणनीति में पहला अंडा गिराया गया हो।

अगर पहला अंडा फूटा, $$m$$ से है $$1$$ को $$a$$ और अधिक से अधिक का उपयोग कर अलग पहचान $$t-1$$ कोशिश करता है और $$n-1$$ अंडे।

अगर पहला अंडा नहीं फूटा, $$m$$ से है $$a+1$$ को $$k$$ और अलग पहचान का उपयोग कर $$t-1$$ कोशिश करता है और $$n$$ अंडे।

इसलिए, $$f(t,n) = f(t-1,n-1) + f(t-1,n)$$.

फिर समस्या न्यूनतम खोजने के बराबर है $$x$$ ऐसा है कि $$f(x,n) \geq k$$.

ऐसा करने के लिए, हम गणना कर सकते हैं $$\{ f(t,i) : 0 \leq i \leq n \}$$ बढ़ाने के क्रम में $$t$$, जो लगेगा $$O( n x )$$ समय।

इस प्रकार, यदि हम अलग से के मामले को संभालते हैं $$n=1$$, एल्गोरिथम लगेगा $$O( n \sqrt{k} )$$ समय।

लेकिन पुनरावृत्ति संबंध वास्तव में हल करके हल किया जा सकता है $$f(t,n) = \sum_{i=0}^{n}{ \binom{t}{i} }$$, जिसकी गणना की जा सकती है $$O(n)$$ पहचान का उपयोग करते हुए समय $$\binom{t}{i+1} = \binom{t}{i} \frac{t-i}{i+1}$$ सभी के लिए $$i \geq 0$$.

तब से $$f(t,n) \leq f(t+1,n)$$ सभी के लिए $$t \geq 0$$, हम बाइनरी सर्च कर सकते हैं $$t$$ ढूँढ़ने के लिए $$x$$, एक दे रहा है $$O( n \log k )$$ कलन विधि।

मैट्रिक्स श्रृंखला गुणन
मैट्रिक्स श्रृंखला गुणन एक प्रसिद्ध उदाहरण है जो गतिशील प्रोग्रामिंग की उपयोगिता को प्रदर्शित करता है। उदाहरण के लिए, इंजीनियरिंग अनुप्रयोगों को अक्सर मेट्रिसेस की एक श्रृंखला को गुणा करना पड़ता है। बड़े आयामों के आव्यूहों को खोजना आश्चर्यजनक नहीं है, उदाहरण के लिए 100×100। इसलिए, हमारा काम मैट्रिसेस को गुणा करना है $A_1, A_2, .... A_n$. मैट्रिक्स गुणन विनिमेय नहीं है, लेकिन साहचर्य है; और हम एक समय में केवल दो आव्यूहों का ही गुणा कर सकते हैं। इसलिए, हम मैट्रिक्स की इस श्रृंखला को कई अलग-अलग तरीकों से गुणा कर सकते हैं, उदाहरण के लिए:



और इसी तरह। मैट्रिसेस की इस श्रृंखला को गुणा करने के कई तरीके हैं। वे सभी एक ही अंतिम परिणाम देंगे, हालांकि उन्हें गणना करने में अधिक या कम समय लगेगा, जिसके आधार पर विशेष मैट्रिक्स को गुणा किया जाता है। यदि मैट्रिक्स A का आयाम m×n है और मैट्रिक्स B का आयाम n×q है, तो मैट्रिक्स C=A×B का आयाम m×q होगा, और इसके लिए m*n*q स्केलर गुणन की आवश्यकता होगी (उद्देश्यों के लिए एक सरलीकृत मैट्रिक्स गुणन एल्गोरिथ्म का उपयोग करके) चित्रण का)।

उदाहरण के लिए, आइए आव्यूहों A, B और C का गुणा करें। मान लें कि उनकी विमाएँ क्रमशः m×n, n×p और p×s हैं। मैट्रिक्स A×B×C का आकार m×s होगा और इसकी गणना नीचे दिखाए गए दो तरीकों से की जा सकती है:


 * 1) एक्स (बी × सी) मैट्रिक्स गुणा के इस क्रम में एनपीएस + एमएनएस स्केलर गुणा की आवश्यकता होगी।
 * 2) (A×B)×C मैट्रिक्स गुणन के इस क्रम में mnp + mps स्केलर गणना की आवश्यकता होगी।

मान लें कि m = 10, n = 100, p = 10 और s = 1000 है। इसलिए, श्रृंखला को गुणा करने के पहले तरीके के लिए 1,000,000 + 1,000,000 गणनाओं की आवश्यकता होगी। दूसरे तरीके में केवल 10,000+100,000 गणनाओं की आवश्यकता होगी। जाहिर है, दूसरा तरीका तेज है, और हमें कोष्ठक की उस व्यवस्था का उपयोग करके मैट्रिसेस को गुणा करना चाहिए।

इसलिए, हमारा निष्कर्ष यह है कि कोष्ठकों का क्रम मायने रखता है, और हमारा कार्य कोष्ठकों के इष्टतम क्रम को खोजना है।

इस बिंदु पर, हमारे पास कई विकल्प हैं, जिनमें से एक गतिशील प्रोग्रामिंग एल्गोरिथ्म को डिजाइन करना है जो समस्या को अतिव्यापी समस्याओं में विभाजित करेगा और कोष्ठक की इष्टतम व्यवस्था की गणना करेगा। गतिशील प्रोग्रामिंग समाधान नीचे प्रस्तुत किया गया है।

चलिए m[i,j] को मैट्रिक्स i से मैट्रिक्स j (अर्थात् A) में मैट्रिक्स की एक श्रृंखला को गुणा करने के लिए आवश्यक स्केलर गुणन की न्यूनतम संख्या कहते हैं।i × .... × एj, यानी मैं <= जे)। हम श्रृंखला को कुछ मैट्रिक्स k पर विभाजित करते हैं, जैसे कि i <= k <j, और यह पता लगाने का प्रयास करें कि कौन सा संयोजन न्यूनतम m [i, j] उत्पन्न करता है।

सूत्र है:

अगर मैं = जे, एम [i, जे] = 0 अगर i <j, m[i,j]= min k के सभी संभावित मानों पर (m[i,k]+m[k+1,j] + $p_{i-1}*p_k*p_j$) जहाँ k, i से j − 1 तक है।


 * $p_(i-1)$ मैट्रिक्स i का पंक्ति आयाम है,
 * $p_k$ मैट्रिक्स k का स्तंभ आयाम है,
 * $p_j$ मैट्रिक्स जे का स्तंभ आयाम है।

इस सूत्र को नीचे दिखाए अनुसार कोडित किया जा सकता है, जहां इनपुट पैरामीटर चेन मेट्रिसेस की श्रृंखला है, अर्थात $A_1, A_2, ... A_n$:

फ़ंक्शन ऑप्टिमलमैट्रिक्स चेन पेरेंटेसिस (श्रृंखला) एन = लंबाई (श्रृंखला) मैं = 1, एन के लिए m[i,i] = 0 // चूंकि इसमें एक मैट्रिक्स को गुणा करने के लिए कोई गणना नहीं होती है लेन = 2, एन के लिए मैं = 1, एन - लेन + 1 के लिए जे = आई + लेन -1 एम [आई, जे] = अनंत  // ताकि पहली गणना अपडेट हो  के = मैं, जे -1 के लिए q = m[i, k] + m[k+1, j] + $p_{i-1}*p_k*p_j$ अगर q <m[i, j] // कोष्ठकों का नया क्रम हमारे पास जो था उससे बेहतर है एम [आई, जे] = क्यू  // अपडेट  s[i, j] = k // रिकॉर्ड करें कि किस k पर विभाजन करना है, यानी कोष्ठक कहां लगाना है

अब तक, हमने सभी संभव के लिए मूल्यों की गणना की है $((A_{1} × A_{2}) × A_{3}) × ... A_{n}$, मैट्रिक्स i से मैट्रिक्स j तक एक श्रृंखला को गुणा करने के लिए गणनाओं की न्यूनतम संख्या, और हमने संबंधित विभाजन बिंदु दर्ज किया है$A_{1}×(((A_{2}×A_{3})× ... ) × A_{n})$. उदाहरण के लिए, यदि हम श्रृंखला को गुणा कर रहे हैं $(A_{1} × A_{2}) × (A_{3} × ... A_{n})$, और यह पता चला है $m[i, j]$ और $s[i, j]$, इसका मतलब है कि मैट्रिक्स 1 से 3 के लिए कोष्ठक का इष्टतम स्थान है $(A_1\times A_2)\times A_3$ और उन आव्यूहों को गुणा करने के लिए 100 अदिश गणनाओं की आवश्यकता होगी।

यह एल्गोरिद्म टेबल m[, ] और s[, ] तैयार करेगा जिसमें i और j के सभी संभावित मानों की प्रविष्टियां होंगी। संपूर्ण श्रृंखला के लिए अंतिम समाधान m [1, n] है, जो s [1, n] पर संबंधित विभाजन के साथ है। समाधान को खोलना पुनरावर्ती होगा, ऊपर से शुरू होकर तब तक जारी रहेगा जब तक हम आधार मामले तक नहीं पहुंच जाते, यानी एकल मैट्रिसेस का गुणन।

इसलिए, अगला कदम वास्तव में श्रृंखला को विभाजित करना है, अर्थात कोष्ठक को वहां रखना है जहां वे (इष्टतम रूप से) संबंधित हैं। इस उद्देश्य के लिए हम निम्नलिखित एल्गोरिथम का उपयोग कर सकते हैं:

'फ़ंक्शन' PrintOptimalParenthesis(s, i, j)    'अगर' मैं = जे प्रिंट ए मैं 'अन्य' प्रिंट (        PrintOptimalParenthesis(s, i, s[i, j])         PrintOptimalParenthesis(s, s[i, j] + 1, j)         प्रिंट)

बेशक, यह एल्गोरिदम वास्तविक गुणा के लिए उपयोगी नहीं है। परिणाम कैसा दिखता है यह देखने के लिए यह एल्गोरिथ्म सिर्फ एक उपयोगकर्ता के अनुकूल तरीका है।

वास्तव में उचित विभाजन का उपयोग करके मेट्रिसेस को गुणा करने के लिए, हमें निम्नलिखित एल्गोरिथम की आवश्यकता है: <वाक्यविन्यास लैंग = जावास्क्रिप्ट> function MatrixChainMultiply(1 से n तक की श्रृंखला) // अंतिम मैट्रिक्स लौटाता है, यानी A1×A2×... ×An OptimalMatrixChainParenthesis (1 से n तक की श्रृंखला) // यह s [ उत्पन्न करेगा। ] और एम [. ] टेबल्स OptimalMatrixMultiplication(s, 1 से n तक की श्रृंखला) // वास्तव में गुणा करें

function OptimalMatrixMultiplication(s, i, j) // इष्टतम तरीके से एआई से एजे तक मैट्रिक्स की एक श्रृंखला को गुणा करने का परिणाम देता है अगर मैं <जे // श्रृंखला को विभाजित करना जारी रखें और मेट्रिसेस को बाएँ और दाएँ पक्ष में गुणा करें लेफ्टसाइड = ऑप्टिमलमैट्रिक्स मल्टीप्लिकेशन (एस, आई, एस[आई, जे]) राइटसाइड = ऑप्टिमलमैट्रिक्स मल्टीप्लिकेशन (एस, एस [आई, जे] + 1, जे) रिटर्न मैट्रिक्स मल्टीप्लाई (लेफ्टसाइड, राइटसाइड) और अगर मैं = जे रिटर्न एआई//मैट्रिक्स स्थिति i पर अन्य प्रिंट एरर, i <= j को होल्ड करना चाहिए

function MatrixMultiply(A, B) // फ़ंक्शन जो दो मैट्रिक्स को गुणा करता है अगर कॉलम (ए) = पंक्तियां (बी) i = 1 के लिए, पंक्तियाँ (A) जे = 1 के लिए, कॉलम (बी) सी [आई, जे] = 0 के = 1 के लिए, कॉलम (ए) सी [आई, जे] = सी [आई, जे] + ए [आई, के] * बी [के, जे] वापसी सी अन्य प्रिंट त्रुटि, असंगत आयाम। 

इतिहास
डायनेमिक प्रोग्रामिंग शब्द का उपयोग मूल रूप से 1940 के दशक में रिचर्ड बेलमैन द्वारा समस्याओं को हल करने की प्रक्रिया का वर्णन करने के लिए किया गया था, जहाँ एक के बाद एक सर्वश्रेष्ठ निर्णय खोजने की आवश्यकता होती है। 1953 तक, उन्होंने इसे आधुनिक अर्थ में परिष्कृत किया, विशेष रूप से बड़े निर्णयों के अंदर छोटी निर्णय समस्याओं को घोंसला बनाने के लिए संदर्भित करते हुए, और उसके बाद क्षेत्र को IEEE द्वारा सिस्टम विश्लेषण और अभियांत्रिकी विषय के रूप में मान्यता दी गई। बेलमैन के योगदान को बेलमैन समीकरण के नाम से याद किया जाता है, जो गतिशील प्रोग्रामिंग का एक केंद्रीय परिणाम है जो पुनरावर्तन (कंप्यूटर विज्ञान) रूप में एक अनुकूलन समस्या को पुनर्स्थापित करता है।

बेलमैन अपनी आत्मकथा, आई ऑफ द हरिकेन: एन ऑटोबायोग्राफी में डायनामिक प्रोग्रामिंग शब्द के पीछे तर्क बताते हैं:

"I spent the Fall quarter (of 1950) at RAND. My first task was to find a name for multistage decision processes. An interesting question is, "Where did the name, dynamic programming, come from?" The 1950s were not good years for mathematical research. We had a very interesting gentleman in Washington named Wilson. He was Secretary of Defense, and he actually had a pathological fear and hatred of the word "research". I’m not using the term lightly; I’m using it precisely. His face would suffuse, he would turn red, and he would get violent if people used the term research in his presence. You can imagine how he felt, then, about the term mathematical. The RAND Corporation was employed by the Air Force, and the Air Force had Wilson as its boss, essentially. Hence, I felt I had to do something to shield Wilson and the Air Force from the fact that I was really doing mathematics inside the RAND Corporation. What title, what name, could I choose? In the first place I was interested in planning, in decision making, in thinking. But planning, is not a good word for various reasons. I decided therefore to use the word "programming". I wanted to get across the idea that this was dynamic, this was multistage, this was time-varying. I thought, let's kill two birds with one stone. Let's take a word that has an absolutely precise meaning, namely dynamic, in the classical physical sense. It also has a very interesting property as an adjective, and that is it's impossible to use the word dynamic in a pejorative sense. Try thinking of some combination that will possibly give it a pejorative meaning. It's impossible. Thus, I thought dynamic programming was a good name. It was something not even a Congressman could object to. So I used it as an umbrella for my activities."

- Richard Bellman

समस्याओं के समय-भिन्न पहलू को पकड़ने के लिए बेलमैन द्वारा गतिशील शब्द चुना गया था, और क्योंकि यह प्रभावशाली लग रहा था। प्रोग्रामिंग शब्द प्रशिक्षण या रसद के लिए एक सैन्य कार्यक्रम के अर्थ में, इष्टतम कार्यक्रम खोजने के लिए विधि के उपयोग को संदर्भित करता है। यह प्रयोग रैखिक प्रोग्रामिंग और गणितीय प्रोग्रामिंग वाक्यांशों के समान है, जो गणितीय अनुकूलन का एक पर्याय है। शब्द की उत्पत्ति की उपरोक्त व्याख्या में कमी है। जैसा कि रसेल और नॉर्विग ने अपनी किताब में उपरोक्त कहानी का जिक्र करते हुए लिखा है: यह पूरी तरह से सच नहीं हो सकता, क्योंकि इस शब्द का इस्तेमाल करने वाला उनका पहला पेपर (बेलमैन, 1952) 1953 में विल्सन के रक्षा सचिव बनने से पहले छपा था। साथ ही, Harold J. Kushner के एक भाषण में एक टिप्पणी है, जहां उसे बेलमैन की याद आती है। बेलमैन के बारे में बोलते हुए कुश्नर को उद्धृत करते हुए: दूसरी ओर, जब मैंने उनसे वही सवाल पूछा, तो उन्होंने जवाब दिया कि वह डायनेमिक जोड़कर डेंटज़िग की रैखिक प्रोग्रामिंग को ऊपर उठाने की कोशिश कर रहे थे। शायद दोनों प्रेरणाएँ सच थीं।

डायनेमिक प्रोग्रामिंग का उपयोग करने वाले एल्गोरिदम

 * प्रोटीन-डीएनए बाइंडिंग के लिए जाली मॉडल का आवर्तक समाधान
 * परिमित-क्षितिज असतत-समय गतिशील अनुकूलन समस्याओं के लिए एक समाधान विधि के रूप में पिछड़ा प्रेरण
 * अनंत-क्षितिज, असतत-समय, छूट, समय-अपरिवर्तनीय प्रणाली में बेलमैन समीकरण को हल करने के लिए अनिर्धारित गुणांक की विधि का उपयोग किया जा सकता है। समय-अपरिवर्तनीय गतिशील अनुकूलन समस्याएं
 * कई स्ट्रिंग (कंप्यूटर साइंस) एल्गोरिदम जिनमें सबसे लंबी सामान्य अनुवर्ती समस्या, सबसे लंबी बढ़ती अनुवर्ती समस्या, सबसे लंबी सामान्य सबस्ट्रिंग समस्या, लेवेनशेटिन दूरी (दूरी संपादित करें) शामिल हैं
 * ग्राफ के पेड़ अपघटन पर गतिशील प्रोग्रामिंग का उपयोग करके अप्रत्यक्ष ग्राफ पर कई एल्गोरिदमिक समस्याओं को बाध्य पेड़ की चौड़ाई या बाध्य क्लिक-चौड़ाई के ग्राफ के लिए कुशलतापूर्वक हल किया जा सकता है।
 * CYK एल्गोरिथम | कॉके-यंगर-कसामी (CYK) एल्गोरिथम जो यह निर्धारित करता है कि दिए गए संदर्भ-मुक्त व्याकरण द्वारा दी गई स्ट्रिंग को कैसे और कैसे उत्पन्न किया जा सकता है
 * वर्ड रैप | नुथ का वर्ड रैपिंग एल्गोरिथम जो वर्ड रैपिंग टेक्स्ट के दौरान रैग्डनेस को कम करता है
 * कंप्यूटर शतरंज में ट्रांसपोजिशन टेबल और खंडन तालिका का उपयोग
 * Viterbi एल्गोरिथ्म (छुपे छिपा हुआ मार्कोव मॉडल के लिए उपयोग किया जाता है, और विशेष रूप से भाषण टैगिंग के भाग में)
 * अर्ली एल्गोरिथम (एक प्रकार का चार्ट पार्सर)
 * नीडलमैन-वुन्श एल्गोरिथम और जैव सूचना विज्ञान में उपयोग किए जाने वाले अन्य एल्गोरिदम, जिसमें अनुक्रम संरेखण, संरचनात्मक संरेखण, आरएनए संरचना शामिल है * फ्लोयड-वॉर्शल एल्गोरिथम|फ्लोयड का ऑल-पेयर शॉर्टेस्ट पाथ एल्गोरिथम
 * श्रृंखला मैट्रिक्स गुणन के क्रम का अनुकूलन
 * सबसेट योग समस्या, नैपसैक समस्या और विभाजन समस्या समस्याओं के लिए छद्म-बहुपद समय एल्गोरिदम
 * दो समय श्रृंखला के बीच वैश्विक दूरी की गणना के लिए गतिशील समय वारिंग एल्गोरिदम
 * रिलेशनल डेटाबेस क्वेरी ऑप्टिमाइज़ेशन के लिए पेट्रीसिया सेलिंगर (उर्फ आईबीएम सिस्टम आर) एल्गोरिथम
 * बी-स्पलाइन वक्रों के मूल्यांकन के लिए दे बूर अल्गोरिथम
 * क्रिकेट के खेल बाधित होने पर समस्या के समाधान के लिए डकवर्थ-लुईस पद्धति
 * मार्कोव निर्णय प्रक्रियाओं को हल करने के लिए मूल्य पुनरावृत्ति विधि
 * फोटोशॉप में चुंबक चयन उपकरण जैसे चयन विधियों के बाद कुछ ग्राफिक इमेज एज
 * अंतराल समयबद्धन समस्याओं को हल करने के लिए कुछ तरीके
 * ट्रैवलिंग सेल्समैन की समस्या को हल करने के कुछ तरीके, या तो बिल्कुल (घातीय समय में) या लगभग (जैसे बिटोनिक टूर के माध्यम से)
 * रिकर्सिव कम से कम वर्ग विधि
 * संगीत सूचना पुनर्प्राप्ति में बीट (संगीत) ट्रैकिंग
 * कृत्रिम तंत्रिका नेटवर्क के लिए अनुकूली-आलोचक प्रशिक्षण रणनीति
 * स्टीरियो विजन में उपयोग की जाने वाली पत्राचार समस्या को हल करने के लिए स्टीरियो एल्गोरिदम
 * सीम नक्काशी (सामग्री-जागरूक छवि का आकार बदलना)
 * बेलमैन-फोर्ड एल्गोरिथम एक ग्राफ में सबसे छोटी दूरी खोजने के लिए
 * रैखिक खोज समस्या के लिए कुछ अनुमानित समाधान विधियाँ
 * कडाने का एल्गोरिथम अधिकतम सबर्रे समस्या के लिए
 * वीन ऑटोमैटिक सिस्टम प्लानिंग (WASP) पैकेज में बिजली उत्पादन विस्तार योजनाओं का अनुकूलन

अग्रिम पठन

 * . An accessible introduction to dynamic programming in economics. MATLAB code for the book.
 * . Includes an extensive bibliography of the literature in the area, up to the year 1954.
 * . Dover paperback edition (2003), ISBN 0-486-42809-5.
 * . Especially pp. 323–69.

बाहरी संबंध

 * A Tutorial on Dynamic programming
 * MIT course on algorithms - Includes 4 video lectures on DP, lectures 19-22
 * Applied Mathematical Programming by Bradley, Hax, and Magnanti, Chapter 11
 * More DP Notes
 * King, Ian, 2002 (1987), "A Simple Introduction to Dynamic Programming in Macroeconomic Models." An introduction to dynamic programming as an important tool in economic theory.
 * Dynamic Programming: from novice to advanced A TopCoder.com article by Dumitru on Dynamic Programming
 * Algebraic Dynamic Programming – a formalized framework for dynamic programming, including an entry-level course to DP, University of Bielefeld
 * Dreyfus, Stuart, "Richard Bellman on the birth of Dynamic Programming."
 * Dynamic programming tutorial
 * A Gentle Introduction to Dynamic Programming and the Viterbi Algorithm
 * Tabled Prolog BProlog, XSB, SWI-Prolog
 * IFORS online interactive dynamic programming modules including, shortest path, traveling salesman, knapsack, false coin, egg dropping, bridge and torch, replacement, chained matrix products, and critical path problem.