Comparing DFS(recursive) + DP(memoization) vs General Recursion + DP (memoization) - recursion

I have been using DFS + memoization type approach to solve DP problems. Till now it had worked perfectly for every problem. But recently when I tried it for 0/1 knapsack problem it gave TLE in geeksforgeeks but works fine in Leetcode.
General approach is either consider current element or move forward in the array.
But the approach which I use is, I explicitly mention in a for loop where it must go. Like for eg either go to 2nd or 3rd or... or 10th element. I have analysed my approach and it seems for me. But i am unable to understand why it gives TLE.
Code of my approach which gives TLE is:
int dp[1001][1001];
int util(int indx, int cur_weight, int n,int weights[], int values[]){
if(dp[indx][cur_weight]!=-1)return dp[indx][cur_weight];
int mx_val=0;
for(int i=indx+1;i<n;i++){
if(cur_weight-weights[i]>=0)
mx_val=max(mx_val, util(i,cur_weight-weights[i],n,weights,values));
}
dp[indx][cur_weight]=mx_val+values[indx];
return dp[indx][cur_weight];
}
int knapSack(int W, int wt[], int val[], int n)
{
memset(dp, -1, sizeof(dp));
int mx_val=0;
for(int i=0;i<n;i++){
if(wt[i]<=W)
mx_val=max(mx_val,util(i,W-wt[i],n,wt,val));
dp[i][W]=mx_val;
}
return mx_val;
}
Code of another solution which uses standard DP solution and doesn't give TLE is:
int dp[1001][1001];
int answer(int w, int wt[], int val[], int n){
if(n == 0 || w == 0)
return 0;
if(dp[n-1][w] != -1)
return dp[n-1][w];
if(wt[n-1] <= w){
return dp[n-1][w] = max(val[n-1] + answer(w-wt[n-1], wt, val, n-1), answer(w, wt, val, n-1));
}
return dp[n-1][w] = answer(w, wt, val, n-1);
}
int knapSack(int W, int wt[], int val[], int n)
{
// Your code here
memset(dp, -1, sizeof(dp));
return answer(W, wt, val, n);
}
Can anyone please help?

Related

Weird output on recursive QuickSort

I'm trying to implement a recursive quicksort in C that does all swapping by using bitwise XOR operations. Here is what I've got so far:
//bitwise recursive quicksort
void quicksort(int *int_array,int p, int r){
if(p<r){
int q = part(int_array, p, r);
quicksort(int_array,p, q-1);
quicksort(int_array, q+1, r);
}
}
//Partition
int part(int *int_array, int p, int r){
int pivot = int_array[r];
int i = p-1;
int j;
for(j = p; j<=r-1; j++){
if(int_array[j] <= pivot){
i++;
int_array[i] = int_array[i] ^ int_array[j];
int_array[j] = int_array[i] ^ int_array[j];
int_array[i] = int_array[i] ^ int_array[j];
}
}
int_array[i+1] = int_array[i+1] ^ int_array[r];
int_array[r] = int_array[i+1] ^ int_array[r];
int_array[i+1] = int_array[i+1] ^ int_array[r];
return i+1;
}
When I run this code on an array of 20 ints, 19 out of 20 of them get changed to 0. Any idea why? I can't see anything wrong with the XOR swapping. Any help appreciated, thanks!
The XOR swap algorithm doesn't work when swapping an item with itself, because any number XORed with itself will be 0, the algorithm relies on there being two locations. So after the first line you have just wiped the value.
XOR swap algorithm:
However, the algorithm fails if x and y use the same storage location, since the value stored in that location will be zeroed out by the first XOR instruction, and then remain zero; it will not be "swapped with itself". Note that this is not the same as if x and y have the same values. The trouble only comes when x and y use the same storage location, in which case their values must already be equal.
You can just put a test around your swaps to make sure you never try swapping an element with itself:
int part(int *int_array, int p, int r){
int pivot = int_array[r];
int i = p-1;
int j;
for(j = p; j<=r-1; j++){
if(int_array[j] <= pivot){
i++;
if(i != j) // avoid XORing item with itself
{
int_array[i] = int_array[i] ^ int_array[j];
int_array[j] = int_array[i] ^ int_array[j];
int_array[i] = int_array[i] ^ int_array[j];
}
}
}
if(i+1 != r) // avoid XORing item with itself
{
int_array[i+1] = int_array[i+1] ^ int_array[r];
int_array[r] = int_array[i+1] ^ int_array[r];
int_array[i+1] = int_array[i+1] ^ int_array[r];
}
return i+1;
}

What's wrong with my dynamic programming solution for uva 10739?

I'm solving this problem on uva. I've found the recurrence relation and it works perfectly for the given test cases. However, without memoization, it exceeds time limit. I cached the values and returned the cache(basic memoization). With caching, I'm getting an answer of 1 more than the actual answer for the last two test cases. I can't understand what might be the bug because it works if you take out the caching. Thanks for your help.
Code:
#include<iostream>
using namespace std;
string a;
int n;
int dp[1005][1005];
int solve(int i, int j, int moves)
{
if(j<=i)
return dp[i][j] = moves;
if(dp[i][j]!=-1)
return dp[i][j];
if(a[i]==a[j])
return dp[i][j] = solve(i+1, j-1, moves);
else
return dp[i][j] = min(min(solve(i+1, j-1, moves+1), solve(i+1, j, moves+1)), solve(i, j-1, moves+1));
}
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> a;
n = a.length();
memset(dp, -1, sizeof(dp));
int ans = solve(0, n-1, 0);
cout << ans << "\n";
}
}
Expected O/P for:
sadrulhabibchowdhury: 8
My Output: 9

explore elements of a categorical vector in rcpp

my question is trivial, but I'm new with RCPP and still have not mastered. I wanted to make a function that given a categorical vector and two integers returns the subset of vector content between the two integers. You know, ["A","B","C","D] and 1 and 2, returns me ["B","C"].
I did the next code but doesn't work.
// [[Rcpp::export]]
Rcpp::StringVector Segment(Rcpp::StringVector x, int start, int end) {
Rcpp::StringVector s(end-start+1);
for(int i=start; i <= end; i++){
s[i]=x[i];
}
return(s);
}
Try to use CharacterVector. The solution could be like this.
// [[Rcpp::export]]
CharacterVector Segment( CharacterVector x, int start, int end){
CharacterVector r(end-start+1);
int ind=0;
for( int i=0; i<=r.size(); i++){
if((i>=start) & (i<=end)){
r[ind]=x[i];
ind+=1;
}
}
return(r);
}

Convert a natural number to binary using recursion

I have to convert a natural number to binary but using recursion. I did but without recursion:
int main (){
int n,pot,bin;
printf("Digite o Numero:\n");
scanf("%d",&n);
pot=1;
bin=0;
while (n>0){
bin+=(n%2)*pot;
pot*=10;
n= n/2;
}
printf ("%d",bin);
getch();
return 0;
}
something like (ASSUMING n is positive!):
void getBin(uint n, int pot, int* bin) {
*bin += (n%2)*pot;
n /= 2;
if (n <= 0) {
return;
}
getBin(n, pot * 10, bin);
}
Just to be on the safe side this does not convert a positive number to binary. It creates a number that, when displayed in base 10, looks like the argument in base 2.
A better solution would be to convert the number to char* in a given base.
int getBin(int n) {
return getBinHelper(n, 1, 0);
}
int getBinHelper(int n, int e, int acc) {
return n == 0 ?
acc :
getBinHelper( n/2, e*10, n&1 ? acc+e : acc);
}

Recursion in C unable to return result from the prototype!?

I'm not sure why this recursion is not working! I'm trying to get the total of an input from i=0 to n. I'm also testing recursion instead of 'for loop' to see how it performs. Program runs properly but stops after the input. I would appreciate any comments, thx!
int sigma (int n)
{
if (n <= 0) // Base Call
return 1;
else {
printf ("%d", n);
int sum = sigma( n+sigma(n-1) );
return sum;
}
// recursive call to calculate any sum>0;
// for example: input=3; sum=(3+sigma(3-1)); sum=(3+sigma(2))
// do sigma(2)=2+sigma(2-1)=2+sigma(1);
// so sigma(1)=1+sigma(1-1)=1+sigma(0)=1;
// finally, sigma(3)=3+2+1+0=6
}
int main (int argc, char *argv[])
{
int n;
printf("Enter a positive integer for sum : ");
scanf( " %d ", &n);
int sum = sigma(n);
printf("The sum of all numbers for your entry: %d\n", sum);
getch();
return 0;
}
Change
int sum = sigma( n+sigma(n-1) );
to
int sum = n + sigma( n-1 );
As you've written it, calling sigma(3) then calls sigma(5), etc...
Also, return 0 from the guard case, not 1.
I think it should be
int sum = n + sigma(n-1)

Resources