- Definition: Dynamic Programming (DP) is a method for solving problems by breaking them down into smaller, overlapping subproblems, which are solved only once and stored for reuse. - Applications: DP is widely used in optimization problems, like shortest paths in graphs, resource allocation, and sequence alignment in computational biology. - Example Problem: Calculating the nth Fibonacci number efficiently using DP.
STEP 1 - Understand the Problem
- Objective: To solve problems efficiently by reusing solutions to smaller subproblems. - Example - Fibonacci Sequence: Given an integer n, calculate the nth Fibonacci number where: - F(0) = 0 - F(1) = 1 - F(n) = F(n-1) + F(n-2) for n > 1 - Goal: Avoid redundant calculations by storing intermediate results.
STEP 2 - Formulate a Model
- Identify the Subproblems: Recognize that each Fibonacci number relies on the results of previous Fibonacci numbers, making this a problem with overlapping subproblems. - Establish the Optimal Substructure: The optimal solution for F(n) depends on the optimal solutions of F(n-1) and F(n-2). - Model Approach: Use either: - Top-Down (Memoization): Cache results of subproblems as they are computed. - Bottom-Up (Tabulation): Build a table from the smallest subproblems up to the target problem.
STEP 3 - Develop an Algorithm
- Choose an Approach: Select memoization (top-down) or tabulation (bottom-up) based on the problem requirements. - Plan the Steps: - Memoization: Recursively calculate each Fibonacci number, storing each result. - Tabulation: Iteratively fill a table, starting from the base cases, up to F(n). - Algorithm Example: (Provide pseudocode for both memoization and tabulation for Fibonacci calculation) STEP 4 - Write the Program - Memorization Implementation:
def fib_memo(n, memo={}):
if n in memo: print(f"Retrieving memoized result for fib({n}) = {memo[n]}") return memo[n] if n <= 1: print(f"Base case reached for fib({n}) = {n} | Current memo state: {memo}") return n # Calculate, store in memo, and print intermediate results result = fib_memo(n-1, memo) + fib_memo(n-2, memo) memo[n] = result print(f"Computed fib({n}) = {result} | Updated memo state: {memo}") return result
# Running the function for the first 10 Fibonacci numbers
for i in range(7): print(f"Final result for fib({i}) = {fib_memo(i)}\n")
- Tabulation Implementation:
#bottoum up (it starts from the base cases)
def fib_tab(n): if n <= 1: print(f"Base case reached for fib({n}) = {n}") return n
# Initialize the table to store intermediate results
for i in range(2, n + 1): fib_table[i] = fib_table[i - 1] + fib_table[i - 2] print(f"Computed fib({i}) = {fib_table[i]} | Updated table state: {fib_table}")
# The nth Fibonacci number is at the nth index of fib_table
return fib_table[n]
# Running the function for the first 7 Fibonacci numbers
for i in range(7,8): print(f"Final result for fib({i}) = {fib_tab(i)}\n") - Compiling and Running: Ensure there are no syntax errors and run the code with sample inputs. STEP 5 - Test the Program - Purpose: Verify that the solution is correct for a variety of inputs. - Test Cases: Use cases like n = 5, n = 10, and edge cases (e.g., n = 0, n = 1) to ensure accuracy. - Debugging: Check for errors if output is incorrect, ensuring all intermediate calculations are stored and retrieved as expected.
STEP 6 - Evaluate the Solution
- Efficiency Analysis: - Time Complexity: Memoization and tabulation improve the Fibonacci sequence calculation from O(2^n) (naive recursion) to O(n). - Space Complexity: Both methods require O(n) space for storage. - Interpret Results: Confirm the program's efficiency and correctness; consider if the chosen method is optimal for similar DP problems.
Download Complete EASA Module 11A B1 Turbine Aeroplane Aerodynamics Structures and Systems 4th Edition Aircraft Technical Book Company Llc PDF for All Chapters