lixolas's blog

By lixolas, history, 11 months ago, , Yup, you read it right ;)

I know this isn't really a big thing, but still is something that might help when you are about to code a DP which has to optimized in memory.

So, take, for instance the Knapsack problem:

Background

You have N items, each with profit Pi and weight Wi. You want to fit the items in a Knapsack with max capacity of B. What is the max profit you can have?

The usual solution for this DP uses 2 dimensions: dp[i][j] stores the max profit using until the i-th item, with total weight j. So we have the following recursion:

dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - Wi] + Pi).

"Ok, but what is this all for anyway?"

So, first notice that we are dealing with 2 dimensions; the first one is just an index for the items, and the second one is the capacity we are dealing with right now. Also, notice that we are only going backwards in the second dimension. Because of this structure, we could replace the classic 2-dimension code by the following:

for(int i=0; i<N; i++) {
for(int j=B; j>=0; j--) {
if(j - W[i] >= 0) {
dp[j] = max(dp[j], dp[j-W[i]] + P[i]);
}
}
}

To retrieve the answer, just take max(dp[j]) between all valid j.

This trick only works because we are walking backwards in the weight dimension instead of forwards. So, when we are updating the DP, we won't mess up and risk using the same item twice (which could easily happen if we went forwards with j). This strategy is sometimes useful when you want to use a DP which goes well in time, but not so much in memory =P

This could be used in the recent contest problem 1078B - The Unbearable Lightness of Weights, and this was, actually, my motivation for writing this blog. My AC submission uses this logic: 45977998.

A little down: you can't recover the list of the items by this method, only the rock-solid answer.

That's it, folks! Have a good day/noon/night! ;) #dp,
By lixolas, history, 23 months ago, , Hello everyone,

on last CodeForces, the problem A of Div1 Contest (this problem) was about some GCD operations. My solution (by the way, totally overkill, despite the fact that some people may have used the same idea) used binary search and some prefix sum matrix (for checking if GCD on range equals 1), only considering primes smaller than 40,050. Although it is getting AC (my solution during the contest, translated to english), I figured out a case where it fails:

2

524287 524287

(actually, it could be any prime numbers greater than 40,050.)

In this case the solution is -1 (because the gcd of two equal numbers is the number itself), however, my code prints 1 as the answer. Is there anything that can be done about this? gcd,
By lixolas, history, 2 years ago, , 