5

Example 1:

Shop selling beer, available packages are 6 and 10 units per package. Customer inputs 26 and algorithm replies 26, because 26 = 10 + 10 + 6.

Example 2:

Selling spices, available packages are 0.6, 1.5 and 3. Target value = 5. Algorithm returns value 5.1, because it is the nearest greater number than target possible to achieve with packages (3, 1.5, 0.6).

I need a Java method that will suggest that number.

Simmilar algorithm is described in Bin packing problem, but it doesn't suit me. I tried it and when it returned me the number smaller than target I was runnig it once again with increased target number. But it is not efficient when number of packages is huge.

I need almost the same algorithm, but with the equal or greater nearest number.

Similar question: Find if a number is a possible sum of two or more numbers in a given set - python.

Community
  • 1
  • 1
  • You gave me tips that i already knew. My aim was to get a pure method that will work properly, So your answer is not better than others that i found googling. And the suggestion of yours: "Simple algorithm" takes to much time. – user3380170 Mar 09 '14 at 19:19
  • What do you mean by "pure method"? What we provided is a pseudopolynomial, optimal solution which is probably as good as it can get, seening as the problem is NP-hard. Also, in the future, please include stuff you already know in the questions. Otherwise how are we going to know what it is that you need to know? – Niklas B. Mar 09 '14 at 19:23
  • You can always write comments on answers to ask for clarifications if something is unclear to you. – Niklas B. Mar 09 '14 at 19:26

2 Answers2

4

First let's reduce this problem to integers rather than real numbers, otherwise we won't get a fast optimal algorithm out of this. For example, let's multiply all numbers by 100 and then just round it to the next integer. So say we have item sizes x1, ..., xn and target size Y. We want to minimize the value

k1 x1 + ... + kn xn - Y

under the conditions

(1) ki is a non-positive integer for all n ≥ i ≥ 1

(2) k1 x1 + ... + kn xn - Y ≥ 0

One simple algorithm for this would be to ask a series of questions like

  1. Can we achieve k1 x1 + ... + kn xn = Y + 0?
  2. Can we achieve k1 x1 + ... + kn xn = Y + 1?
  3. Can we achieve k1 x1 + ... + kn xn = Y + z?
  4. etc. with increasing z

until we get the answer "Yes". All of these problems are instances of the Knapsack problem with the weights set equal to the values of the items. The good news is that we can solve all those at once, if we can establish an upper bound for z. It's easy to show that there is a solution with z ≤ Y, unless all the xi are larger than Y, in which case the solution is just to pick the smallest xi.

So let's use the pseudopolynomial dynamic programming approach to solve Knapsack: Let f(i,j) be 1 iif we can reach total item size j with the first i items (x1, ..., xi). We have the recurrence

f(0,0) = 1
f(0,j) = 0   for all j > 0
f(i,j) = f(i - 1, j) or f(i - 1, j - x_i) or f(i - 1, j - 2 * x_i) ...

We can solve this DP array in O(n * Y) time and O(Y) space. The result will be the first j ≥ Y with f(n, j) = 1.

There are a few technical details that are left as an exercise to the reader:

  • How to implement this in Java
  • How to reconstruct the solution if needed. This can be done in O(n) time using the DP array (but then we need O(n * Y) space to remember the whole thing).
Community
  • 1
  • 1
Niklas B.
  • 92,950
  • 18
  • 194
  • 224
0

You want to solve the integer programming problem min(ct) s.t. ct >= T, c >= 0 where T is your target weight, and c is a non-negative integer vector specifying how much of each package to purchase, and t is the vector specifying the weight of each package. You can either solve this with dynamic programming as pointed out by another answer, or, if your weights and target weight are too large then you can use general integer programming solvers, which have been highly optimized over the years to give good speed performance in practice.

user2566092
  • 4,631
  • 15
  • 20