0

This is the recursive function

def integerPartition(m, n):
    if(n==0):
        return 0
    if(m ==0):
        return 1
    if(m<0):
        return 0

    return integerPartition(m,n-1) + integerPartition(m-n,n)

and this is what i have done in c++

        // n -> no. of persons
        // m -> amount of money to be distributed
        // dp table of order (n+1)*(m+1) 
        long long int dp[n+1][m+1] ;
        //initializing values to 0
        for(i = 0; i<=n ; i++)
            for(j = 0; j<= m ; j++)
                dp[i][j] = 0;

        Print(n,m,dp);
        cout << "\n";
        //Case 1 - if there is no persons i.e n = 0 answer will be 0
        //Case 2 - if there is no money i.e. m = 0 there is only 1 way answer will be 1
        for ( i = 1; i<= n ; i++ )
            dp[i][0] = 1;
            dp[i][i] = 1;

        Print(n,m,dp);

        for ( i = 1; i<= n ; i++){
            for ( j = 1; j<= m ; j++){
                dp[i][j] = dp[i][j-1] ;

                if(i>=j){
                    dp[i][j] += dp[i-j][j];
                }
                // else if(i==j){
                //     dp[i][j] += 1;
                // }
            }
    }

but the answers i am getting are not matching with the recursive one i don't understand what am i missing if anyone can please help me to correct i will be thankful since i have just started with dynamic programming i really am not able to figure it out

nikhil6041
  • 55
  • 1
  • 8
  • When you run this with a debugger, what is the first point at which it behaves differently than you expected? – Scott Hunter Dec 26 '19 at 13:42
  • Welcome to StackOverflow. See [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). We cannot effectively help you until you post your MRE code and accurately specify the problem. We should be able to paste your posted code into a text file and reproduce the problem you specified. Since you haven't specified your problem, you're not likely to get any specific help. – Prune Dec 26 '19 at 15:45

3 Answers3

2

Some issues:

  • You seem to use non-local variables for your for loops. This is bad practice and can lead to errors that are difficult to debug. Instead do for (int i = 1; ...etc.

  • dp[i][i] = 1; is not part of the for loop. You would have detected this if you would have defined i only as a variable local to the for loop. It is good practice to always use braces for the body of a for loop (also if, else, ...etc), even if you would only have one statement in the body.

  • dp[i][i] = 1; is also a bad assignment: it just is not true that integerPartition(i, i) always returns 1. It happens to be true for small values of i, but not when i is greater than 3. For instance, integerPartition(4, 4) should return 5. Just remove this line.

  • In the final nested for loop you are mixing up the row/column in your dp array. Note that you had reserved the first dimension for n and the second dimension for m, so opposite to the parameter order. That is fine, but you do not stick to that decision in this for loop. Instead of dp[i][j-1] you should have written dp[i-1][j], and instead of dp[i-j][j] you should have written dp[i][j-i]. And so the if condition should be adapted accordingly.

  • There is no return statement in your version, but maybe you just forgot to include it in the question. It should be return dp[n][m];

Here is the corrected code:

long long int dp[n+1][m+1];

for(int i = 0; i <=n; i++) {
    for(int j = 0; j <= m; j++) {
        dp[i][j] = 0;
    }
}

for (int i = 1; i <= n; i++) {
    dp[i][0] = 1;
}

for (int i = 1; i <= n; i++){
    for (int j = 1; j <= m ; j++) {
        dp[i][j] = dp[i-1][j];
        if (j >= i) {
            dp[i][j] += dp[i][j-i];
        }
    }
}

return dp[n][m];
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thanks for your help and yeah i agree i messed up in that decisions for assignments and i was having a hard time to find out my error can you suggest me what is the approach i should follow to convert any recursive function like this into a dp based approach – nikhil6041 Dec 27 '19 at 05:31
  • I don't think there is a general method to convert any recursive method to a DP based approach. Some recursive algorithms cannot even be turned in to DP, because the base case is not known at the start, only when the recursion brings information down the recursion tree. For instance a depth-first search in a graph will mark nodes as visited, and the base case is when a node has no unvisited neighbors. You don't know those nodes beforehand. – trincot Dec 27 '19 at 07:15
0

Not sure that this technically is DP, but if your goal is to get the benefits of DP, memorization might be a better approach.

The idea is made up of 2 parts:

  1. At the start of each call to integerPartition, look up in a table (your dp will do nicely) to see if that computation has already been done, and if it has, just return the value stored in the table.

  2. Just before any point where integerPartition is to return a value, store it in the table.

Note that this means you don't need to try to "pivot" the original code -- it proceeds as it did originally, so you are almost guaranteed to get the same results, but without as much unnecessary re-computation (at the code of extra storage).

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • Thanks @Scott Hunter but can u check out my cpp code and tell me where am i wrong i am not getting it if possible – nikhil6041 Dec 26 '19 at 13:18
0

so, basis of your code comment, I am going to assume you only want 1 when n > 0 and m = 0 according to your recursive code, but in dp code, you interchanged them, that is i go to upto n, and j go upto m so updating your code, try to find the mistake


        // n -> no. of persons
        // m -> amount of money to be distributed
        // dp table of order (n+1)*(m+1) 
        long long int dp[n+1][m+1] ;
        //initializing values to 0
        for(i = 0; i<=n ; i++)
            for(j = 0; j<= m ; j++)
                dp[i][j] = 0;

        Print(n,m,dp);
        cout << "\n";
        //Case 1 - if there is no persons i.e n = 0 answer will be 0
        //Case 2 - if there is no money i.e. m = 0 there is only 1 way answer will be 1

        for ( i = 1; i<= n; i++){
            dp[i][0] = 0;
        }

        for(int j = 1; j <= m; j++){
            dp[0][j] = 1;
        }

        Print(n,m,dp);

        for ( i = 1; i<= n ; i++){
            for ( j = 1; j<= m ; j++){
                dp[i][j] = dp[i][j-1] ;

                if(i>=j){
                    dp[i][j] += dp[i-j][j];
                }
                // else if(i==j){
                //     dp[i][j] += 1;
                // }
            }
    }

mss
  • 1,423
  • 2
  • 9
  • 18