I can tell yes... It is not working fine but you can go for some work around that I may not be preferable with.
But recently I was working with 0/1 knapsack problem where If I go with the tail recursion approach or the head recursion approach that result
it gives is correct. But If I try to apply DP(Dynamic Programming) in it. It is failing in the scence giving the wrong answer.
let me give a sample input here
int n = 7;
vector<int> weight = {6, 5, 1, 5, 6, 5, 9};
vector<int> value = {5, 3, 4, 9, 6, 1, 1};
int maxWeight = 13;
If I use 2-D vector as my DP array to optimise it. I will paste the code below but here is now the function call and the values in DP are getting stored
for this example I am taking the index of the weight vector and the maxWeight values
f(0,13)->f(2,7)->f(2,2)->f(3,1)->f(4,1)->f(5,1)->f(6,1) and when returning back it start to store in dp like dp[6,1] = 12->dp[5,1] = 12->dp[4,1] = 12->dp[3,1] = 12->dp[2,2] = 12..... But it should not get stored in this way this is the problem with tail recursion where the result is also passed with the function so that the state changes are not captured correctly If you work out the full example we will get a clear clarity.
where as in the head recursion the ans or the result is not going to be returned that value will get added up as you can see in the below code so these mismatch of state won't occur.
#include <bits/stdc++.h>
using namespace std;
int kps_tail_rec(vector<int> &weight, vector<int> &value, int i, int &n, int maxWeight, int ans, vector<vector<int>> &dp) {
cout<<"start of func - > i= "<<i<<", maxWeight= "<<maxWeight<<endl;
if (i == n || maxWeight == 0)
return ans;
if (dp[i][maxWeight]){
cout<<"i= "<<i<<", maxWeight= "<<maxWeight<<" , dp[i][maxWeight] = "<<dp[i][maxWeight]<<endl;
return dp[i][maxWeight];
}
int taken = 0, nottaken = 0;
if (weight[i] <= maxWeight) {
taken = kps_tail_rec(weight, value, i + 1, n, maxWeight - weight[i], ans + value[i], dp);
}
nottaken = kps_tail_rec(weight, value, i + 1, n, maxWeight, ans, dp);
cout<<"for this i and maxWeight"<<i<<", "<<maxWeight<<"taken= "<<taken<<", nottaken= "<<nottaken<<endl;
return dp[i][maxWeight] = max(taken, nottaken);
}
int kps_head_rec(vector<int> &weight, vector<int> &value, int i, int &n, int maxWeight, vector<vector<int>> &dp) {
cout<<"start of func - > i= "<<i<<", maxWeight= "<<maxWeight<<endl;
if (i == n || maxWeight == 0)
return 0;
if (dp[i][maxWeight]){
cout<<"i= "<<i<<", maxWeight= "<<maxWeight<<" , dp[i][maxWeight] = "<<dp[i][maxWeight]<<endl;
return dp[i][maxWeight];
}
int taken = 0, nottaken = 0;
if (weight[i] <= maxWeight) {
taken = value[i] + kps_head_rec(weight, value, i + 1, n, maxWeight - weight[i], dp);
}
nottaken = kps_head_rec(weight, value, i + 1, n, maxWeight, dp);
cout<<"for this i and maxWeight"<<i<<", "<<maxWeight<<"taken= "<<taken<<", nottaken= "<<nottaken<<endl;
return dp[i][maxWeight] = max(taken, nottaken);
}
int knapsack(vector<int> weight, vector<int> value, int n, int maxWeight) {
vector<vector<int>> dp(n + 1, vector<int>(maxWeight + 1, 0));
cout << kps_tail_rec(weight, value, 0, n, maxWeight, 0, dp)<<" , ";
cout<<" now going for the 2nd approch\n";
vector<vector<int>> dp1(n + 1, vector<int>(maxWeight + 1, 0));
cout << kps_head_rec(weight, value, 0, n, maxWeight, dp1);
return 0;
}
int main() {
int n = 7;
vector<int> weight = {6, 5, 1, 5, 6, 5, 9};
vector<int> value = {5, 3, 4, 9, 6, 1, 1};
int maxWeight = 13;
int result = knapsack(weight, value, n, maxWeight);
return 0;
}
Summary : In recurrsion both tail and head gives the same value but when we Optimise with DP going with Head recursion is a better option.
enter code here