Reputation: 24500
This is from dp tutorial on CodeChef, I'm tracing it.
Details: when I enter if clause - i print "STEP 1"/step2/step3. The program works fine.
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std ;
#define min(a,b) ( (a) < (b) ? (a) : (b))
int memo[10 + 1] ;
void reset_memo()
{
cout << endl ;
cout << "RESETTING MEMO" << endl ;
for (int i = 0 ; i < 11 ; i++) {
memo[i] = -1 ;
}
}
int getMinSteps(int n)
{
cout << "======current n : " << n << " ===============" << endl ;
if (n == 1) {
cout << "BASE CASE n = 1 and returning 0..." << endl ;
return 0;
} // base case
if (memo[n] != -1) {
return memo[n];
} // we have solved it already :)
cout << "STEP 1 " << endl ;
int r = 1 + getMinSteps(n - 1); // '-1' step . 'r' will contain the optimal answer finally
if (n % 2 == 0) {
cout << " STEP 2: " << endl ;
r = min(r , 1 + getMinSteps(n / 2)) ;
} // '/2' step
if (n % 3 == 0) {
cout << " STEP 3: " << endl ;
r = min(r , 1 + getMinSteps(n / 3)) ;
} // '/3' step
memo[n] = r ; // save the result. If you forget this step, then its same as plain recursion.
return r;
}
I spent 5 hours trying to understand one little detail:
OUTPUT:
RESETTING MEMO
enter next number
2
===============current n 2 ===============
STEP 1:
===============current n 1 ===============
BASE CASE n = 1 and returning 0...
STEP 2:
===============current n 1 ===============
BASE CASE n = 1 and returning 0...
===============current n 1 ===============
BASE CASE n = 1 and returning 0...
RESULT 1
RESETTING MEMO enter next number
why does it call the black highlighted last piece of code "BASE CASE ...." ?
I clearly don't see it! it should only be there once please help figure out - I don't see where exactly additional call happens!
Upvotes: 1
Views: 117
Reputation: 1712
I tested the program under the debugger and min( )
causes the getMinSteps(n / 2)
to be called twice. This is because of the macro definition you have that is using b
two times #define min(a,b) ( (a) < (b) ? (a) : (b))
causing a side effect. Try to use std:min instead.
Here is another workaround for the case n % 2 == 0
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std ;
#define min(a,b) ( (a) < (b) ? (a) : (b))
int memo[10 + 1] ;
void reset_memo()
{
cout << endl ;
cout << "RESETTING MEMO" << endl ;
for (int i = 0 ; i < 11 ; i++) {
memo[i] = -1 ;
}
}
int getMinSteps(int n)
{
cout << "======current n : " << n << " ===============" << endl ;
if (n == 1) {
cout << "BASE CASE n = 1 and returning 0..." << endl ;
return 0;
} // base case
if (memo[n] != -1) {
return memo[n];
} // we have solved it already :)
cout << "STEP 1 " << endl ;
int r = 1 + getMinSteps(n - 1); // '-1' step . 'r' will contain the optimal answer finally
if (n % 2 == 0) {
cout << " STEP 2: " << endl ;
int v = getMinSteps(n / 2); // <--- so getMinSteps will be called only once!
r = min(r , 1 + v) ;
} // '/2' step
if (n % 3 == 0) {
cout << " STEP 3: " << endl ;
r = min(r , 1 + getMinSteps(n / 3)) ;
} // '/3' step
memo[n] = r ; // save the result. If you forget this step, then its same as plain recursion.
return r;
}
int main(){
reset_memo();
getMinSteps(2);
getchar();
getchar();
}
Upvotes: 1