Reputation: 3996
I am currently practicing some dynamic programming and I came across the Circus Tower problem.
I solved the problem with dynamic programming and implemented it using recursion. I've tested it with few inputs and it seems to work fine.
Now, I've been struggling few hours trying to figure out how to add memoization to my solution.
Questions
The Circus Tower Problem: A circus is designing a tower of people standing atop one another’s shoulders. Each person must be both shorter and lighter than the person below him. Given the heights and weights of each person in the circus, write a method to compute the largest possible number of people in such a tower.
My Solution & Code
Dynamic Programming
OPT[N,P] = highest tower with N given persons and person P is at the top
----------------------------------------------------------
OPT[0,P] = 0
OPT[i,P] where person i can be above P = max(OPT[i-1,i]+1,OPT[i-1,P])
OPT[i,P] else = OPT[i-1,P]
Code:
struct Person{
int ht;
int wt;
};
// Without Memoization
int circusTower(int n, Person* top, std::vector<Person>& persons){
if (n == 0)
return 0;
if (top == NULL || top->ht > persons[n - 1].ht && top->wt > persons[n - 1].wt)
return max(circusTower(n - 1, &persons[n - 1], persons) + 1, circusTower(n - 1, top, persons));
else
return circusTower(n - 1, top, persons);
}
// With Memoization
int circusTower(int n, Person* top, std::vector<Person>& persons, std::vector<int>& memo){
if (n == 0)
return 0;
int result;
if (memo[n-1] == 0) {
if (top == NULL || top->ht > persons[n - 1].ht && top->wt > persons[n - 1].wt)
result = max(circusTower(n - 1, &persons[n - 1], persons, memo) + 1,
circusTower(n - 1, top, persons, memo));
else
result = circusTower(n - 1, top, persons, memo);
memo[n - 1] = result;
return result;
} else {
return memo[n-1];
}
}
Main - test:
int main(){
std::vector<Person> persons = { {65, 100},{100, 150},{56, 90}, {75, 190}, {60, 95},{68, 110} };
std::stable_sort(persons.begin(), persons.end(), sortByWt);
std::stable_sort(persons.begin(), persons.end(), sortByHt);
std::vector<int> memo(6,0);
//Without memoization
cout << circusTower(6, NULL, persons) << endl;
//With memoization
cout << circusTower(6, NULL, persons, memo) << endl;
}
In the example inside the main above, the right result is 5. My regular solution (without memoization) prints 5, but with memoization it prints 6.
Upvotes: 1
Views: 716
Reputation: 217275
Your method depend of 3 arguments
but you memoize only from the first argument n
Indeed in your case, the third one (persons
) is constant,
but the second one (top
) changes during the recursive call.
so due to your memoization, both the following return wrongly the same value:
circusTower(n - 1, &persons[n - 1], persons, memo)
circusTower(n - 1, top, persons, memo)
Upvotes: 2