Complete the code to check if a problem has optimal substructure property.
def has_optimal_substructure(problem): # If solution can be built from solutions of subproblems return problem.can_build_solution_from_subproblems() and problem.has_[1]()
The optimal substructure property means the optimal solution can be constructed from optimal solutions of its subproblems.
Complete the code to check if a problem has the greedy choice property.
def has_greedy_choice_property(problem): # If local optimal choice leads to global optimum return problem.can_make_local_choice() and problem.has_[1]()
The greedy choice property means making the best local choice at each step leads to a global optimum.
Fix the error in the function that decides which approach to apply.
def choose_approach(problem): if problem.has_optimal_substructure() and problem.has_[1](): return 'Dynamic Programming' elif problem.has_greedy_choice_property(): return 'Greedy' else: return 'Brute Force'
Dynamic programming requires both optimal substructure and overlapping subproblems.
Fill both blanks to complete the function that explains why greedy works.
def explain_greedy(problem): if problem.has_[1]() and problem.has_[2](): return 'Greedy approach is suitable' else: return 'Greedy approach may fail'
Greedy algorithms require greedy choice property and optimal substructure to guarantee correct solutions.
Fill all three blanks to complete the function that decides approach based on problem properties.
def decide_approach(problem): if problem.has_[1]() and problem.has_[2](): return 'Dynamic Programming' elif problem.has_[3](): return 'Greedy' else: return 'Brute Force'
Dynamic programming needs optimal substructure and overlapping subproblems; greedy needs greedy choice property.
