Coin making problem in DP - getting wrong answer using 2dimensional memo table - algorithm

When I am passing this Input I am getting wrong answer
coin[] = {5,6}
Amount(W) = 10
my answer = 1
Correct Answer should be 2 i.e {5,5}
void coin_make(int W, vector<int> coin){
int n = coin.size();
int dp[n+1][W+1];
for(int i = 0; i <=W; i++){
dp[0][i] = INT_MAX;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= W; j++){
if(coin[i-1] == j){
dp[i][j] = 1;
}
else if(coin[i-1] > j){
dp[i][j] = dp[i-1][j];
}
else {
dp[i][j] = min(dp[i-1][j],
1 + dp[i][j-coin[i-1]]);
}
}
}
cout<<dp[n][W];}

You're overflowing on dp[1][6], since you try to calculate 1 + INT_MAX. This error propagates further and finally the answer is not correct. When I ran it on my machine, I got -2147483648. You should use some other constant as "infinity" to prevent overflows (e.g. 2e9 (or -1, but this would require some additional if statements)). Then the code will work fine on your provided test case.

Related

How to convert this recursive function to a dp based solution?

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
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];
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:
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.
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).
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;
// }
}
}

what's wrong in this heapifying algorithm

i'm not sure what wrong with my code and its not converting the array into heap.please help!!!
pointer a is the pointer to the array passing to the function(you must have figured out that by now) and z is the length of the array.
please do explain me why i'm wrong.
i'm noob at coding(you must have figured out that also by my code for sure).
thank you for your precious time.
int heapy(int *a,int z)
{
for(i = 0; i<z ;i++)
{ c[i] = a[i];
for(j = i; j >= 0; --j)
{ y = (j-1)/2;
if(c[j] > c[y])
{ temp = c[y];
c[y] = c[j];
c[j] = temp;
j = y;}
else
break;
}
}
}
First point: You don't need the loop over j and that is where you have your problem. That is true, that you should assign y value to j, but just after that you decrement j in loop, so finally you get y - 1.
What you should do is either just change line j = y; to j = y + 1, or change the loop to
y = (j - 1) / 2
while (c[j] > c[y]){
temp = c[y];
c[y] = c[j];
c[j] = temp;
j = y;
y = (j - 1) / 2;
}
Second point: please do not compress your code like this. New line after bracket is much more readable.
EDIT:
Full implementation in C++ looks like this:
int heapy(int *a, int *c, int z)
{
for (int i = 0; i < z; i++){
c[i] = a[i];
int j = i;
int y = (j - 1) / 2;
while(c[j] > c[y]){
int temp = c[y];
c[y] = c[j];
c[j] = temp;
j = y;
y = (j - 1) / 2;
}
}
}
If array of i elements is a heap than you should add element on its end and swap it with it's parents as long as they are less than it.
In short: your program is too long by three characters: just remove --j from it.

Google Foobar, maximum unique visits under a resource limit, negative weights in graph

I'm having trouble figuring out the type of problem this is. I'm still a student and haven't taken a graph theory/linear optimization class yet.
The only thing I know for sure is to check for negative cycles, as this means you can rack the resource limit up to infinity, allowing for you to pick up each rabbit. I don't know the "reason" to pick the next path. I also don't know when to terminate, as you could keep using all of the edges and make the resource limit drop below 0 forever, but never escape.
I'm not really looking for code (as this is a coding challenge), only the type of problem this is (Ex: Max Flow, Longest Path, Shortest Path, etc.) If you an algorithm that fits this already that would be extra awesome. Thanks.
The time it takes to move from your starting point to all of the bunnies and to the bulkhead will be given to you in a square matrix of integers. Each row will tell you the time it takes to get to the start, first bunny, second bunny, ..., last bunny, and the bulkhead in that order. The order of the rows follows the same pattern (start, each bunny, bulkhead). The bunnies can jump into your arms, so picking them up is instantaneous, and arriving at the bulkhead at the same time as it seals still allows for a successful, if dramatic, escape. (Don't worry, any bunnies you don't pick up will be able to escape with you since they no longer have to carry the ones you did pick up.) You can revisit different spots if you wish, and moving to the bulkhead doesn't mean you have to immediately leave - you can move to and from the bulkhead to pick up additional bunnies if time permits.
In addition to spending time traveling between bunnies, some paths interact with the space station's security checkpoints and add time back to the clock. Adding time to the clock will delay the closing of the bulkhead doors, and if the time goes back up to 0 or a positive number after the doors have already closed, it triggers the bulkhead to reopen. Therefore, it might be possible to walk in a circle and keep gaining time: that is, each time a path is traversed, the same amount of time is used or added.
Write a function of the form answer(times, time_limit) to calculate the most bunnies you can pick up and which bunnies they are, while still escaping through the bulkhead before the doors close for good. If there are multiple sets of bunnies of the same size, return the set of bunnies with the lowest prisoner IDs (as indexes) in sorted order. The bunnies are represented as a sorted list by prisoner ID, with the first bunny being 0. There are at most 5 bunnies, and time_limit is a non-negative integer that is at most 999.
It's a planning problem, basically. The generic approach to planning is to identify the possible states of the world, the initial state, transitions between states, and the final states. Then search the graph that this data imply, most simply using breadth-first search.
For this problem, the relevant state is (1) how much time is left (2) which rabbits we've picked up (3) where we are right now. This means 1,000 clock settings (I'll talk about added time in a minute) times 2^5 = 32 subsets of bunnies times 7 positions = 224,000 possible states, which is a lot for a human but not a computer.
We can deal with added time by swiping a trick from Johnson's algorithm. As Tymur suggests in a comment, run Bellman--Ford and either find a negative cycle (in which case all rabbits can be saved by running around the negative cycle enough times first) or potentials that, when applied, make all times nonnegative. Don't forget to adjust the starting time by the difference in potential between the starting position and the bulkhead.
There you go. I started Google Foobar yesterday. I'll be starting Level 5 shortly. This was my 2nd problem here at level 4. The solution is fast enough as I tried memoizing the states without using the utils class. Anyway, loved the experience. This was by far the best problem solved by me since I got to use Floyd-Warshall(to find the negative cycle if it exists), Bellman-Ford(as a utility function to the weight readjustment step used popularly in algorithms like Johnson's and Suurballe's), Johnson(weight readjustment!), DFS(for recursing over steps) and even memoization using a self-designed hashing function :)
Happy Coding!!
public class Solution
{
public static final int INF = 100000000;
public static final int MEMO_SIZE = 10000;
public static int[] lookup;
public static int[] lookup_for_bunnies;
public static int getHashValue(int[] state, int loc)
{
int hashval = 0;
for(int i = 0; i < state.length; i++)
hashval += state[i] * (1 << i);
hashval += (1 << loc) * 100;
return hashval % MEMO_SIZE;
}
public static boolean findNegativeCycle(int[][] times)
{
int i, j, k;
int checkSum = 0;
int V = times.length;
int[][] graph = new int[V][V];
for(i = 0; i < V; i++)
for(j = 0; j < V; j++)
{
graph[i][j] = times[i][j];
checkSum += times[i][j];
}
if(checkSum == 0)
return true;
for(k = 0; k < V; k++)
for(i = 0; i < V; i++)
for(j = 0; j < V; j++)
if(graph[i][j] > graph[i][k] + graph[k][j])
graph[i][j] = graph[i][k] + graph[k][j];
for(i = 0; i < V; i++)
if(graph[i][i] < 0)
return true;
return false;
}
public static void dfs(int[][] times, int[] state, int loc, int tm, int[] res)
{
int V = times.length;
if(loc == V - 1)
{
int rescued = countArr(state);
int maxRescued = countArr(res);
if(maxRescued < rescued)
for(int i = 0; i < V; i++)
res[i] = state[i];
if(rescued == V - 2)
return;
}
else if(loc > 0)
state[loc] = 1;
int hashval = getHashValue(state, loc);
if(tm < lookup[hashval])
return;
else if(tm == lookup[hashval] && countArr(state) <= lookup_for_bunnies[loc])
return;
else
{
lookup_for_bunnies[loc] = countArr(state);
lookup[hashval] = tm;
for(int i = 0; i < V; i++)
{
if(i != loc && (tm - times[loc][i]) >= 0)
{
boolean stateCache = state[i] == 1;
dfs(times, state, i, tm - times[loc][i], res);
if(stateCache)
state[i] = 1;
else
state[i] = 0;
}
}
}
}
public static int countArr(int[] arr)
{
int counter = 0;
for(int i = 0; i < arr.length; i++)
if(arr[i] == 1)
counter++;
return counter;
}
public static int bellmanFord(int[][] adj, int times_limit)
{
int V = adj.length;
int i, j, k;
int[][] graph = new int[V + 1][V + 1];
for(i = 1; i <= V; i++)
graph[i][0] = INF;
for(i = 0; i < V; i++)
for(j = 0; j < V; j++)
graph[i + 1][j + 1] = adj[i][j];
int[] distance = new int[V + 1] ;
for(i = 1; i <= V; i++)
distance[i] = INF;
for(i = 1; i <= V; i++)
for(j = 0; j <= V; j++)
{
int minDist = INF;
for(k = 0; k <= V; k++)
if(graph[k][j] != INF)
minDist = Math.min(minDist, distance[k] + graph[k][j]);
distance[j] = Math.min(distance[j], minDist);
}
for(i = 0; i < V; i++)
for(j = 0; j < V; j++)
adj[i][j] += distance[i + 1] - distance[j + 1];
return times_limit + distance[1] - distance[V];
}
public static int[] solution(int[][] times, int times_limit)
{
int V = times.length;
if(V == 2)
return new int[]{};
if(findNegativeCycle(times))
{
int ans[] = new int[times.length - 2];
for(int i = 0; i < ans.length; i++)
ans[i] = i;
return ans;
}
lookup = new int[MEMO_SIZE];
lookup_for_bunnies = new int[V];
for(int i = 0; i < V; i++)
lookup_for_bunnies[i] = -1;
times_limit = bellmanFord(times, times_limit);
int initial[] = new int[V];
int res[] = new int[V];
dfs(times, initial, 0, times_limit, res);
int len = countArr(res);
int ans[] = new int[len];
int counter = 0;
for(int i = 0; i < res.length; i++)
if(res[i] == 1)
{
ans[counter++] = i - 1;
if(counter == len)
break;
}
return ans;
}
}

Is this algorithm for the function correct?

The question I'm trying to solve is...
What is the value returned by the following function? Express your answer as a function of n.
int v = 0;
int n = 100;
for (int i = 1; i <= n ; i++)
{
for( int j = n + 1; j < 2 * n; j++)
{
v = v + 1;
}
}
System.out.println(v);
Seems like I'm missing something but I don't know what. =/ Thank you.
I don't want to give the whole answer away.
First of, our function looks like this.
int v = 0;
for (int i = 1; i <= n; i++) {
for (int j = (n + 1); j <= (n*2); j++) {
v++;
}
}
System.out.println(v);
So, depending on n what will v give us?
Let's try it, let's try for n = 1 to 20
for (int n = 1; n < 20; n++) {
int v = 0;
for (int i = 1; i <= n; i++) {
for (int j = (n + 1); j <= (n*2); j++) {
v++;
}
}
System.out.println(v);
}
Try that! If you still are curious give a poke here.
Hint #2. It is a very specific function, a very common.

change coin implementation issue

I ran into an implementation problem when trying to solve this classic problem using DP.
The problem is given a set of coins, and return the number of ways of making a change.
The DP equation is something like the following:
DP[i] += DP[i - coin[j]]
where DP[i] means the number of ways of making change for i.
Here is a straightforward implementation, which is incorrect:
int make_change_wrong(int coin[], int size, int change) {
vector<int> DP(change + 1, 0);
DP[0] = 1;
for (int i = 1; i <= change; ++i) {
for (int j = 0; j < size; ++j) {
if (i - coin[j] >= 0 ) {
DP[i] += DP[i - coin[j]];
}
}
}
return DP[change];
}
Given input:
int coin[] = {1, 5}
change = 6.
make_change_wrong(coin, 2, 6) returns 3, but 2 is correct.
Using the same logic, I re-write it in a less intuitive way and get the correct answer:
int make_change(int coin[], int size, int change) {
vector<int> DP(change + 1, 0);
DP[0] = 1;
for (int i = 0; i < size; ++i) {
for (int j = coin[i]; j <= change; ++j) {
DP[j] += DP[j - coin[i]];
}
}
return DP[change];
}
This puzzled me a lot because to me, they're the same thing...
Can someone illustrate a bit on the problems in the two implementations?
Your first algorithm is wrong.
DP[5] = 2 {1,1,1,1,1}, {5}
DP[6] = DP[5] + DP[1] = 3
you are counting {5,1} twice.
EDITED
So the standard trick for doing this is that you keep a count of the denomination you are allowed to use
DP[i,m] = DP[i-coin[m],m] + DP[i,m-1]
which means number of ways of making a change of i amount using coins in range[1..m].
This is obviously, you either use the mth denomination or you don't.
The second algorithm you are using is doing the same trick but is a really clever way to do that, take the ith coin and see what all change you can generate using it. This will avoid over counting because you avoid doing things like {1,5} and {5,1}.
This problem is in the interview prep book Cracking the Coding Interview, and the solution given in the book is not optimized at all. It uses recursion (without DP) to calculate sub-problems repeatedly and therefore runs in O(N^3) which is especially ironic since it's part of the Dynamic Programming chapter.
Here's a very simple working solution (Java) which uses DP and runs in O(N) time.
static int numCombos(int n) {
int[] dyn = new int[n + 1];
Arrays.fill(dyn, 0);
dyn[0] = 1;
for (int i = 1; i <= n; i++) dyn[i] += dyn[i - 1];
for (int i = 5; i <= n; i++) dyn[i] += dyn[i - 5];
for (int i = 10; i <= n; i++) dyn[i] += dyn[i - 10];
for (int i = 25; i <= n; i++) dyn[i] += dyn[i - 25];
return dyn[n];
}
Please try your input for your second method:
coin[5] = {1,5,10,20,30};
make_change(coin,5,30);
It returns 21. Please check my test case.

Resources