ডায়নামিক প্রোগ্রামিং কী ?
এটি পুনরাবৃত্তি, স্মৃতিচারণ ইত্যাদি থেকে কীভাবে আলাদা?
আমি এটিতে উইকিপিডিয়া নিবন্ধটি পড়েছি , তবে আমি এখনও এটি সত্যি বুঝতে পারি না।
ডায়নামিক প্রোগ্রামিং কী ?
এটি পুনরাবৃত্তি, স্মৃতিচারণ ইত্যাদি থেকে কীভাবে আলাদা?
আমি এটিতে উইকিপিডিয়া নিবন্ধটি পড়েছি , তবে আমি এখনও এটি সত্যি বুঝতে পারি না।
উত্তর:
ডায়নামিক প্রোগ্রামিং হ'ল আপনি যখন ভবিষ্যতের সমস্যা সমাধান করা সহজ করার জন্য অতীত জ্ঞান ব্যবহার করেন।
একটি ভাল উদাহরণ হ'ল ফিবোনাচি সিকোয়েন্সটি n = 1000,002 এর জন্য।
এটি খুব দীর্ঘ প্রক্রিয়া হবে তবে আমি যদি আপনাকে n = 1,000,000 এবং n = 1,000,001 এর ফলাফল দিই? হঠাৎ সমস্যাটি আরও পরিচালনাযোগ্য হয়ে উঠল।
ডায়নামিক প্রোগ্রামিং স্ট্রিং এডিট সমস্যা যেমন স্ট্রিং সমস্যাগুলিতে প্রচুর ব্যবহৃত হয়। আপনি সমস্যার একটি উপসেট (গুলি) সমাধান করুন এবং তারপরে আরও জটিল মূল সমস্যাটি সমাধান করতে সেই তথ্যটি ব্যবহার করুন।
ডায়নামিক প্রোগ্রামিং সহ, আপনি সাধারণত কিছু টেবিলে আপনার ফলাফলগুলি সঞ্চয় করেন। যখন আপনার কোনও সমস্যার জবাব প্রয়োজন তখন আপনি সারণিটি উল্লেখ করে দেখুন এবং এটি ইতিমধ্যে জানেন কি না। যদি তা না হয় তবে আপনি নিজের টেবিলের ডেটা ব্যবহার করে নিজেকে উত্তরের দিকে অগ্রসর হবেন।
করম্যান অ্যালগরিদম বইটিতে ডায়নামিক প্রোগ্রামিং সম্পর্কে একটি দুর্দান্ত অধ্যায় রয়েছে। এবং এটি গুগল বুকে বিনামূল্যে! এটি এখানে দেখুন।
ডায়নামিক প্রোগ্রামিং হ'ল একটি কৌশল যা পুনরাবৃত্ত আলগোরিদিমে একই সাবপ্রব্লেম একাধিকবার গণনা এড়াতে ব্যবহৃত হয়।
আসুন ফিবোনাচি সংখ্যাগুলির সহজ উদাহরণটি গ্রহণ করি: সংজ্ঞায়িত n তম ফিবোনাচি সংখ্যাটি সন্ধান করুন
এফ এন = এফ এন -1 + এফ এন -2 এবং এফ 0 = 0, এফ 1 = 1
এটি করার সুস্পষ্ট উপায়টি পুনরাবৃত্তিযোগ্য:
def fibonacci(n):
if n == 0:
return 0
if n == 1:
return 1
return fibonacci(n - 1) + fibonacci(n - 2)
পুনরাবৃত্তি অনেক অপ্রয়োজনীয় গণনা করে কারণ প্রদত্ত ফিবোনাচি নম্বরটি একাধিকবার গণনা করা হবে। এর উন্নতি করার একটি সহজ উপায় হল ফলাফলগুলি ক্যাশে করা:
cache = {}
def fibonacci(n):
if n == 0:
return 0
if n == 1:
return 1
if n in cache:
return cache[n]
cache[n] = fibonacci(n - 1) + fibonacci(n - 2)
return cache[n]
এটি করার একটি আরও ভাল উপায় হ'ল সঠিক ক্রমে ফলাফলগুলি মূল্যায়ন করে পুনরাবৃত্তিটি সর্বত্র একত্রিত করা:
cache = {}
def fibonacci(n):
cache[0] = 0
cache[1] = 1
for i in range(2, n + 1):
cache[i] = cache[i - 1] + cache[i - 2]
return cache[n]
আমরা এমনকি ধ্রুবক স্থান ব্যবহার করতে পারি এবং কেবল প্রয়োজনীয় আংশিক ফলাফলগুলি পথে সংরক্ষণ করতে পারি:
def fibonacci(n):
fi_minus_2 = 0
fi_minus_1 = 1
for i in range(2, n + 1):
fi = fi_minus_1 + fi_minus_2
fi_minus_1, fi_minus_2 = fi, fi_minus_1
return fi
ডায়নামিক প্রোগ্রামিং কীভাবে প্রয়োগ করবেন?
ডায়নামিক প্রোগ্রামিং সাধারণত সেই সমস্যাগুলির জন্য কাজ করে যাগুলির অন্তর্নিহিত বাম থেকে ডান ক্রম যেমন স্ট্রিং, ট্রি বা পূর্ণসংখ্যার ক্রম। যদি নিষ্কলুষ পুনরাবৃত্তির অ্যালগরিদম একই সাব-প্রব্লেমটিকে একাধিকবার গণনা না করে তবে ডায়নামিক প্রোগ্রামিং সাহায্য করবে না।
যুক্তিটি বুঝতে সহায়তা করার জন্য আমি সমস্যার একটি সংগ্রহ করেছি: https://github.com/tristanguigue/dynamic- প্রোগ্রামিং
if n in cache
উপরের নিচের উদাহরণের মতো বা আমিও কিছু মিস করছি।
মেমোয়েজেশন হ'ল আপনি যখন কোনও ফাংশন কলের পূর্ববর্তী ফলাফলগুলি সঞ্চয় করেন (আসল ফাংশন সর্বদা একই জিনিস দেয়, একই ইনপুটগুলি দেওয়া হয়)। ফলাফল সংরক্ষণের আগে এটি অ্যালগরিদমিক জটিলতার জন্য কোনও পার্থক্য তৈরি করে না।
পুনরাবৃত্তি একটি ফাংশন নিজেই কল করার পদ্ধতি, সাধারণত একটি ছোট ডেটাসেট সহ। যেহেতু বেশিরভাগ পুনরাবৃত্ত ফাংশনগুলি একই ধরণের পুনরাবৃত্ত ফাংশনে রূপান্তর করা যায়, এটি আলগোরিদিমিক জটিলতার জন্য কোনও পার্থক্য করে না।
ডায়নামিক প্রোগ্রামিং হ'ল উপ-সমস্যাগুলি সমাধান করার সহজ সমাধান এবং সেখান থেকে উত্তর তৈরি করার প্রক্রিয়া। বেশিরভাগ ডিপি অ্যালগরিদমগুলি লোভী অ্যালগরিদম (যদি বিদ্যমান থাকে) এবং একটি ক্ষতিকারক (সমস্ত সম্ভাবনার গণনা করুন এবং সেরাটি সন্ধান করুন) অ্যালগরিদমের মধ্যে চলমান সময়ে হবে।
এটি আপনার অ্যালগরিদমের একটি অপ্টিমাইজেশন যা চলমান সময়কে হ্রাস করে।
যদিও লোভী অ্যালগরিদমকে সাধারণত নিখুঁত বলা হয় , কারণ এটি একই সেট ডেটার একাধিকবার চলতে পারে, ডায়নামিক প্রোগ্রামিং চূড়ান্ত সমাধান গঠনে সহায়তা করতে আংশিক ফলাফলগুলির গভীর বোঝার মাধ্যমে এই ক্ষতিটিকে এড়িয়ে চলে।
একটি সহজ উদাহরণ হ'ল নোডগুলির মাধ্যমে গাছ বা একটি গ্রাফকে অনুসরণ করা যা সমাধানে অবদান রাখবে বা আপনি এতক্ষণে যে সমাধানগুলি পেয়েছেন সেগুলি একটি টেবিলের মধ্যে রেখে দিচ্ছেন যাতে আপনি একই নোডগুলি বার বার অতিক্রম করতে পারবেন।
ইউভিএ'র অনলাইন বিচারক থেকে ডায়নামিক প্রোগ্রামিংয়ের জন্য উপযুক্ত এমন সমস্যার উদাহরণ এখানে রয়েছে: পদক্ষেপ মই সম্পাদনা করুন।
আমি প্রোগ্রামিং চ্যালেঞ্জস বইটি থেকে নেওয়া এই সমস্যার বিশ্লেষণের গুরুত্বপূর্ণ অংশটি সম্পর্কে দ্রুত ব্রিফিং করতে যাচ্ছি, আমি আপনাকে এটি পরীক্ষা করে দেখার পরামর্শ দিচ্ছি।
এই সমস্যাটিকে ভাল করে দেখুন, আমরা যদি দুটি স্ট্রিংয়ের পরিমাণ কতটুকু প্রযোজ্য তা ব্যয় করে আমাদের একটি ব্যয় নির্ধারণ করে, আমাদের দুটি প্রাকৃতিক ধরণের পরিবর্তন বিবেচনা করে থাকে:
প্রতিস্থাপন - "শ" থেকে "স্পট" এ পরিবর্তনের মতো পাঠ্য "টি" এর একটি ভিন্ন চরিত্রে প্যাটার্ন "এস" থেকে একটি একক অক্ষর পরিবর্তন করুন।
সন্নিবেশ - পাঠ্য "টি" এর সাথে মেলে "ago" এর সাথে প্যাটার্ন "s" তে একটি অক্ষর সন্নিবেশ করান, যেমন "পূর্বে" "অ্যাগ্রোগ" এ পরিবর্তন করা।
মুছে ফেলা - "টি" এর সাথে টেক্সট মেলাতে সহায়তা করতে প্যাটার্ন "s" থেকে একটি অক্ষর মুছুন, যেমন "ঘন্টা" পরিবর্তন করে "আমাদের" করুন to
যখন আমরা এই পদক্ষেপের প্রতিটি সেট করে এক ধাপ ব্যয় করি তখন আমরা দুটি স্ট্রিংয়ের মধ্যে সম্পাদনার দূরত্বটি নির্ধারণ করি। তাহলে আমরা কীভাবে এটি গণনা করব?
আমরা পর্যবেক্ষণটি ব্যবহার করে একটি পুনরাবৃত্তির অ্যালগরিদম সংজ্ঞায়িত করতে পারি যে স্ট্রিংয়ের শেষ অক্ষরটি অবশ্যই ম্যাচ, প্রতিস্থাপন, sertedোকানো বা মুছে ফেলা উচিত। শেষ সম্পাদনা ক্রিয়াকলাপে অক্ষরগুলি কেটে ফেলার ফলে একটি জুড়ি অপারেশন এক জোড়া ছোট ছোট স্ট্রিং ফেলে। I এবং j যথাক্রমে এবং t এর প্রাসঙ্গিক উপসর্গের সর্বশেষ চরিত্র হয়ে উঠি। শেষ অপারেশনের পরে তিন জোড়া সংক্ষিপ্ত স্ট্রিং রয়েছে, ম্যাচ / প্রতিস্থাপন, সন্নিবেশ বা মোছার পরে স্ট্রিংয়ের সাথে সম্পর্কিত। আমরা যদি তিনটি ছোট স্ট্রিংগুলির সম্পাদনার ব্যয়টি জানতাম, তবে আমরা সিদ্ধান্ত নিতে পারি যে কোন বিকল্পটি সবচেয়ে ভাল সমাধানের দিকে নিয়ে যায় এবং সেই বিকল্পটি সেই অনুযায়ী চয়ন করতে পারি। পুনরাবৃত্তি হওয়া দুর্দান্ত জিনিসটির মাধ্যমে আমরা এই ব্যয়টি শিখতে পারি:
#define MATCH 0 /* enumerated type symbol for match */ #define INSERT 1 /* enumerated type symbol for insert */ #define DELETE 2 /* enumerated type symbol for delete */ int string_compare(char *s, char *t, int i, int j) { int k; /* counter */ int opt[3]; /* cost of the three options */ int lowest_cost; /* lowest cost */ if (i == 0) return(j * indel(’ ’)); if (j == 0) return(i * indel(’ ’)); opt[MATCH] = string_compare(s,t,i-1,j-1) + match(s[i],t[j]); opt[INSERT] = string_compare(s,t,i,j-1) + indel(t[j]); opt[DELETE] = string_compare(s,t,i-1,j) + indel(s[i]); lowest_cost = opt[MATCH]; for (k=INSERT; k<=DELETE; k++) if (opt[k] < lowest_cost) lowest_cost = opt[k]; return( lowest_cost ); }
এই অ্যালগরিদম সঠিক, তবে অসম্ভব ধীর।
আমাদের কম্পিউটারে চলমান, দুটি 11-বর্ণের দুটি স্ট্রিং তুলনা করতে বেশ কয়েক সেকেন্ড সময় লাগে, এবং গণনাটি আর কখনও কখনও কখনও কখনও না ঘটে into
অ্যালগরিদম এত ধীর কেন? এটি ক্ষতিকারক সময় নেয় কারণ এটি বারবার মানগুলি পুনরায় সংশোধন করে। স্ট্রিংয়ের প্রতিটি অবস্থানে, পুনরাবৃত্তিটি তিনটি উপায়ে শাখা করে, এর অর্থ এটি কমপক্ষে 3 ^ n হারে বৃদ্ধি পায় - প্রকৃতপক্ষে, আরও দ্রুত কলগুলি দুটি সূচকগুলির মধ্যে একটি হ্রাস করে, উভয়ই নয়।
তাহলে আমরা কীভাবে অ্যালগরিদমকে ব্যবহারিক করে তুলতে পারি? গুরুত্বপূর্ণ পর্যবেক্ষণটি হ'ল এই পুনরাবৃত্তির কলগুলির মধ্যে বেশিরভাগই এমন জিনিসগুলি কম্পিউটিং করা হয় যা ইতিমধ্যে গণনা করা হয়েছিল। আমরা কিভাবে জানব? ঠিক আছে, কেবলমাত্র | গুলি | · | টি | সম্ভাব্য অনন্য পুনরাবৃত্ত কলগুলি, যেহেতু পুনরাবৃত্ত কলগুলির পরামিতি হিসাবে পরিবেশন করতে কেবলমাত্র অনেকগুলি পৃথক (i, j) জোড়া রয়েছে।
একটি টেবিলের মধ্যে এইগুলির (আই, জে) জোড়াগুলির জন্য মানগুলি সঞ্চয় করে আমরা সেগুলি পুনর্নির্মাণ এড়াতে পারি এবং প্রয়োজন অনুযায়ী সেগুলি সন্ধান করতে পারি।
টেবিলটি একটি দ্বি-মাত্রিক ম্যাট্রিক্স মি যেখানে প্রতিটি | s | · | t | প্রতি কোষগুলিতে এই সাবপ্রব্লেমটির সর্বোত্তম সমাধানের ব্যয় পাশাপাশি আমরা কীভাবে এই অবস্থানে পৌঁছেছি তা বোঝাতে একটি পিতামাতার পয়েন্টার রয়েছে:
typedef struct { int cost; /* cost of reaching this cell */ int parent; /* parent cell */ } cell; cell m[MAXLEN+1][MAXLEN+1]; /* dynamic programming table */
গতিশীল প্রোগ্রামিং সংস্করণটির পুনরাবৃত্ত সংস্করণ থেকে তিনটি পার্থক্য রয়েছে।
প্রথমত, এটি পুনরাবৃত্তির কলগুলির পরিবর্তে টেবিল প্রদর্শন ব্যবহার করে এর মধ্যবর্তী মানগুলি লাভ করে।
** দ্বিতীয়, ** এটি প্রতিটি ঘরের মূল ক্ষেত্র আপডেট করে, যা পরবর্তী সময়ে সম্পাদনা ক্রমটি পুনর্গঠন করতে সক্ষম করবে।
** তৃতীয়, ** তৃতীয়, এটি
cell()
কেবল এম [| এস |] [| টি |]। কোস্ট ফিরে আসার পরিবর্তে আরও সাধারণ লক্ষ্য ফাংশন ব্যবহার করে চালিত হয়। এটি আমাদের সমস্যার বিস্তৃত শ্রেণিতে এই রুটিনটি প্রয়োগ করতে সক্ষম করবে।
এখানে, সর্বাধিক অনুকূল আংশিক ফলাফল সংগ্রহ করতে যা লাগে তার একটি বিশেষ বিশ্লেষণ, যা সমাধানটিকে "গতিশীল" করে তোলে।
এখানে একই সমস্যার একটি বিকল্প, সম্পূর্ণ সমাধান রয়েছে। এটি কার্যকর করার পরেও এটি কার্যকর একটি "গতিশীল"। আমি আপনাকে পরামর্শ দিচ্ছি যে ইউভিএর অনলাইন বিচারকের কাছে জমা দিয়ে সমাধানটি কতটা কার্যকর by আমি এত বিস্ময়কর সমস্যাটি এত দক্ষতার সাথে কীভাবে মোকাবেলা করেছি তা আশ্চর্যজনক বলে মনে করি।
ডায়নামিক প্রোগ্রামিংয়ের মূল বিটগুলি হ'ল "ওভারল্যাপিং সাব-সমস্যাগুলি" এবং "সর্বোত্তম কাঠামো"। সমস্যার এই বৈশিষ্ট্যগুলির অর্থ একটি অনুকূল সমাধান তার উপ-সমস্যার সর্বোত্তম সমাধানগুলির সমন্বয়ে গঠিত। উদাহরণস্বরূপ, সবচেয়ে সংক্ষিপ্ত পথের সমস্যাগুলি সর্বোত্তম কাঠামোগত প্রদর্শন করে। এ থেকে সি পর্যন্ত সংক্ষিপ্ততম পথ হ'ল এ থেকে কিছু নোড বি এর সংক্ষিপ্ততম পথ এবং তারপরে সেই নোড বি থেকে সি পর্যন্ত সবচেয়ে ছোট পথ by
আরও বিশদে বিশদভাবে, একটি সংক্ষিপ্ততম পথের সমস্যাটি সমাধান করার জন্য আপনি:
যেহেতু আমরা নীচে কাজ করছি, আমাদের কাছে ইতিমধ্যে সাব-সমস্যাগুলির সমাধান করার সময় আসে যখন সেগুলি স্মরণে করে ব্যবহার করার সময় আসে।
মনে রাখবেন, ডায়নামিক প্রোগ্রামিং সমস্যার ক্ষেত্রে ওভারল্যাপিং উপ-সমস্যা এবং সর্বোত্তম কাঠামো উভয়ই থাকতে পারে। ফিবোনাচি সিক্যুয়েন্স তৈরি করা গতিশীল প্রোগ্রামিং সমস্যা নয়; এটি মেমোয়েজেশনকে কাজে লাগায় কারণ এতে ওভারল্যাপিং উপ-সমস্যা রয়েছে তবে এটিতে সর্বোত্তম কাঠামো নেই (কারণ এতে কোনও অপ্টিমাইজেশানের সমস্যা নেই)।
ডায়নামিক প্রোগ্রামিং
সংজ্ঞা
ডায়নামিক প্রোগ্রামিং (ডিপি) ওভারল্যাপিং উপ-সমস্যাগুলি নিয়ে সমস্যাগুলি সমাধান করার জন্য একটি সাধারণ অ্যালগরিদম ডিজাইন কৌশল। এই কৌশলটি আমেরিকান গণিতবিদ "রিচার্ড বেলম্যান" 1950 সালে আবিষ্কার করেছিলেন।
কী আইডিয়া
মূল ধারণাটি পুনরায় পুনর্নির্মাণ এড়াতে আরও ছোট ছোট সমস্যাগুলিকে ওভারল্যাপ করার উত্তরগুলি সংরক্ষণ করা।
গতিশীল প্রোগ্রামিংয়ের বৈশিষ্ট্য
আমি ডায়নামিক প্রোগ্রামিংয়েও খুব নতুন (বিশেষ ধরণের সমস্যার জন্য একটি শক্তিশালী অ্যালগরিদম)
সর্বাধিক সহজ কথায়, গতিশীল প্রোগ্রামিংটিকে পূর্ববর্তী জ্ঞানটি ব্যবহার করে পুনরাবৃত্তির পদ্ধতি হিসাবে ভাবেন
পূর্ববর্তী জ্ঞান হ'ল এখানে সর্বাধিক গুরুত্বপূর্ণ, আপনার ইতিমধ্যে যে উপ-সমস্যা রয়েছে তার সমাধানের খোঁজ রাখুন।
এটি বিবেচনা করুন, উইকিপিডিয়া থেকে ডিপি-র জন্য সবচেয়ে প্রাথমিক উদাহরণ
ফিবোনাচি ক্রম সন্ধান করা হচ্ছে
function fib(n) // naive implementation
if n <=1 return n
return fib(n − 1) + fib(n − 2)
এন = 5 দিয়ে ফাংশন কলটি ভেঙে ফেলা যাক
fib(5)
fib(4) + fib(3)
(fib(3) + fib(2)) + (fib(2) + fib(1))
((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
(((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
বিশেষত, ফাইব (2) স্ক্র্যাচ থেকে তিনবার গণনা করা হয়েছিল। বৃহত্তর উদাহরণগুলিতে, ফাইব বা উপ-সমস্যাগুলির আরও অনেক মানগুলি পুনরায় গণনা করা হয়, যা ঘনঘন সময় আলগরিদমের দিকে পরিচালিত করে।
এখন, মানচিত্রটি একটি ডেটা-কাঠামোর মধ্যে আমরা ইতিমধ্যে খুঁজে পেয়েছি যে মানটি সংরক্ষণ করে এটি ব্যবহার করে দেখি
var m := map(0 → 0, 1 → 1)
function fib(n)
if key n is not in map m
m[n] := fib(n − 1) + fib(n − 2)
return m[n]
এখানে আমরা মানচিত্রের উপ-সমস্যার সমাধান সংরক্ষণ করছি, যদি তা ইতিমধ্যে আমাদের কাছে না থাকে। মানগুলি সংরক্ষণের এই কৌশলটি যা আমরা ইতিমধ্যে গণনা করেছি মেমোয়েজেশন হিসাবে অভিহিত।
শেষ পর্যন্ত, কোনও সমস্যার জন্য, প্রথমে রাজ্যগুলি অনুসন্ধান করার চেষ্টা করুন (সম্ভাব্য উপ-সমস্যাগুলি এবং আরও ভাল পুনরাবৃত্তি পদ্ধতির কথা চিন্তা করার চেষ্টা করুন যাতে আপনি পূর্ববর্তী সাব-সমস্যার সমাধানটি আরও একটি ক্ষেত্রে ব্যবহার করতে পারেন)।
ডায়নামিক প্রোগ্রামিং ওভারল্যাপিং সাব সমস্যাগুলির সাথে সমস্যাগুলি সমাধান করার একটি কৌশল। একটি গতিশীল প্রোগ্রামিং অ্যালগরিদম প্রতিটি উপ সমস্যা ঠিক একবার সমাধান করে এবং তারপরে একটি উত্তর সারণিতে (অ্যারে) সংরক্ষণ করে। প্রতিবার সাব সমস্যায় পড়লে উত্তরটি পুনরায় কম্পিউটিংয়ের কাজ এড়ানো। ডায়নামিক প্রোগ্রামিংয়ের অন্তর্নিহিত ধারণাটি হ'ল: একই উপায়ে দু'বার গণনা করা থেকে বিরত থাকুন, সাধারণত উপ সমস্যার পরিচিত ফলাফলগুলির একটি সারণী রেখে।
একটি গতিশীল প্রোগ্রামিং অ্যালগরিদমের বিকাশের সাতটি ধাপ নিম্নরূপ:
6. Convert the memoized recursive algorithm into iterative algorithm
একটি আবশ্যিক পদক্ষেপ? এর অর্থ হ'ল এর চূড়ান্ত রূপটি পুনরাবৃত্তিযোগ্য?
সংক্ষেপে পুনরাবৃত্তি স্মৃতিচারণ এবং ডায়নামিক প্রোগ্রামিংয়ের মধ্যে পার্থক্য
নাম হিসাবে প্রস্তাবিত গতিশীল প্রোগ্রামিংটি পূর্ববর্তী গণনা করা মানটি ব্যবহার করে পরবর্তী নতুন সমাধানটি গতিশীলভাবে তৈরি করতে হয়
ডায়নামিক প্রোগ্রামিং কোথায় প্রয়োগ করবেন: আপনি যদি সমাধানটি সর্বোত্তম কাঠামো এবং ওভারল্যাপিং উপ সমস্যার ভিত্তিতে তৈরি করেন তবে সেক্ষেত্রে পূর্ববর্তী গণনা করা মানটি কার্যকর হবে সুতরাং আপনাকে এটি পুনরায় সংশোধন করতে হবে না। এটি নীচে আপ পদ্ধতির হয়। ধরুন আপনাকে সেই ক্ষেত্রে ফাইব (এন) গণনা করতে হবে আপনার কেবলমাত্র ফাইব (এন-1) এবং ফাইব (এন -2) এর আগের গণনা করা মান যুক্ত করা দরকার
পুনরাবৃত্তি: সহজেই সহজেই সমাধান করার জন্য আপনাকে সমস্যাটিকে ছোট্ট ভাগে বিভক্ত করা তবে মনে রাখবেন এটি পুনরায় গণনা এড়ায় না যদি আমাদের অন্যান্য পুনরাবৃত্তির কলে একই মান নির্ধারণ করা হয়।
স্মৃতিচারণ: মূলত টেবিলে পুরানো গণনা করা পুনরাবৃত্তি মান সংরক্ষণ করা স্মৃতিচারণ হিসাবে পরিচিত যা এর পূর্বেকার কোনও কল দ্বারা গণনা করা থাকলে পুনরায় গণনা এড়াতে পারে তাই কোনও মান একবার গণনা করা হবে। সুতরাং গণনা করার আগে আমরা পরীক্ষা করে নিই যে এই মানটি ইতিমধ্যে গণনা করা হয়েছে কিনা না যদি ইতিমধ্যে গণনা করা হয় তবে আমরা পুনরায় পুনর্নির্মাণের পরিবর্তে টেবিল থেকে একইটি ফিরিয়ে দেব। এটি টপ ডাউন অ্যাপ্রোচও
এখানে একটি সহজ পাইথন কোড উদাহরণ Recursive
, Top-down
, Bottom-up
ফিবানচি সিরিজের জন্য দৃষ্টীকোণ:
def fib_recursive(n):
if n == 1 or n == 2:
return 1
else:
return fib_recursive(n-1) + fib_recursive(n-2)
print(fib_recursive(40))
def fib_memoize_or_top_down(n, mem):
if mem[n] is not 0:
return mem[n]
else:
mem[n] = fib_memoize_or_top_down(n-1, mem) + fib_memoize_or_top_down(n-2, mem)
return mem[n]
n = 40
mem = [0] * (n+1)
mem[1] = 1
mem[2] = 1
print(fib_memoize_or_top_down(n, mem))
def fib_bottom_up(n):
mem = [0] * (n+1)
mem[1] = 1
mem[2] = 1
if n == 1 or n == 2:
return 1
for i in range(3, n+1):
mem[i] = mem[i-1] + mem[i-2]
return mem[n]
print(fib_bottom_up(40))