I have read many variations of the Knapsack problem, but the version I am tasked with is a little different and I don't quite understand how to solve it.
I have an array of integers that represent weights (ie. {1,4,6,12,7,2}) and need to find only one solution that adds up to the target weight.
I understand the basic algorithm, but I cannot understand how to implement it.
First, what is my base case? Is it when the array is empty? The target has been reached? The target has been over-reached? Or maybe some combination?
Second, when the target is over-reached, how do I backtrack and try the next item?
Third, what am I supposed to return? Should I be returning ints (in which case, am I supposed to print them out?)? Or do I return arrays and the final return is the solution?
Think carefully about the problem you are trying to solve. To approach this problem, I am
considering the inputs and outputs of the Knapsack algorithm.
Input: A set of integers (the knapsack) and a single integer (the proposed sum)
Output: A set of integers who add up to the proposed sum, or null.
In this way your code might look like this
public int[] knapsackSolve(int[] sack, int prospectiveSum) {
//your algorithm here
}
The recursive algorithm is straightforward. First compute the sum of the sack. If it equals
prospectiveSum then return the sack. Otherwise iterate over sack, and for each item initialise a new knapsack with that item removed. Call knapsackSolve on this. If there is a solution, return it. Otherwise proceed to the next item.
For example if we call knapsackSolve({1,2,3},5) the algorithm tries 1 + 2 + 3 = 5 which is false. So it loops through {1,2,3} and calls knapsackSolve on the sublists {2,3},{1,3} and {1,2}. knapsackSolve({2,3},5) is the one that returns a solution.
This isn't a very efficient algorithm although it illustrates fairly well how complex the Knapsack problem is!
Basically the Knapsack problem is formulated as (from Wikipedia): "Given a set of items, each with a mass and a value, determine the number of each item to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible. For your problem we are interested in weights only. So you can set all values to 1. Additionally we only want to know if the target weight can be reached exactly. I guess you are allowed to use a weight only once and not multiple times?
This problem can be solved nicely with dynamic programming. Are you familiar with that principle? Applying dynamic programming is much more elegant and quicker to program than backtracking. But if you are only allowed to do backtracking use the approach from user2738608 posted above.
Related
I looked through here and found questions similar but not solving for the equation. Here is what I'm looking to do. I need to be able to determine a collection of equations that potentially can be used to solve a set of input parameters and a result. I will always know the inputs and the results. I need to figure out a way to solve for the solution for lack of a better term.
For instance:
Input parameters: 5,1,1,2
Result: 8
I would like to input these numbers and result and get something like:
FirstNumber(5) * (SecondNumber(1) + ThirdNumber(1)) - FourthNumber(2) = 8
FirstNumber(5) * FourthNumber(2) - SecondNumber(1) - ThirdNumber(1) = 8
Obviously it can be complex and given more numbers could have many possible solutions. My general question is around feasibility.
It is actually quite difficult task to solve.
First - you have to be able to solve any equation with +-*/ and with (). How to do that? You have to create tree-like structure with these operators and be able to count the result.
If you visualize the tree it looks like this:
When you are finished with this task, you can start with generating all the possibilities that can happen. The Backtracking is actually quite useful, as it is automatically remove the paths that does not lead to anything and with proper implementation it finds all possible solutions.
To get a collection of all possible linear equations I would try permutation without repetition for the inputs except the result (ignore possible identical inputs) and permutation taken from each cobination of all operators taken G at a time where G is the number of gaps between input numbers to fill the gaps between numbers and then try every position and size more than one and less than N for the numbers inside of the "()" where N is the number of inputs excluding the result.
Check the answers in this link for how to get permutation in java
Generating all permutations of a given string
I am trying to write a very simple greedy algorithm for the knapsack problem. My inputs are two parallel arrays. One array contains the value of the item and the other array contains the weights.
The greedy algorithm that I’m trying to write would go as follows: check which item has the highest value and put this in the knapsack. Then set the value of this item to zero. Check again which item has the highest value and put it in the knapsack if the knapsack can still hold it. If it can hold it, set the value again to zero (after you’ve put it in) and start looking for the highest value again. If that knapsack cannot hold it anymore then just end the program.
I know that there are a lot of better greedy algorithms out there but this seems to me to be a pretty simple one and I think I could manage this. My problem is that I have to go through the entire values array to find the maximum value. Then when I’ve found it I put it in the knapsack and set the value to zero. But the problem then is that I have to go back in the for loop to find the new highest value item and put this in the knapsack. But I don’t know how I would go about doing this.
I am writing this in Java.
First of all, you usually solve Knapsack greedily by using the highest ratio value/weight instead of just the value.
Secondly, you do not need to search for the maximum in each step if you sort the list of items once and go through it step by step.
The typical objective function of 0-1 Multidimensional Knapsack is to maximize the value of all items in the knapsack. A good algorithm was provided in the Stackexchange link here: 0-1 Multidimensional Knapsack.
However, what if my objective function is to pack as many items in the knapsack as possible? All pieces have equal values. The Stackexchange post (Knapsack problem with all profits equal to 1) claims that a one dimensional knapsack with equal values can be solved by Greedy Algorithm. Is that true? I thought the 01 knapsack problem is NP-hard therefore the greedy algorithm may not give the optimum solution.
So my questions are two-part?
1) can optimum solution be given by greedy algorithm in this case? 01 knapsack with equal values
2) how to implement a multi-dimensional greedy algorithm? the vi/wi is a value divided by a vector...
1.) The knapsack problem IS an NP-Hard problem. So in short, no, you cannot solve it optimally using a greedy algorithm. Instead heuristic approaches exist that can get you very close.
2.) In the case of equal profit knapsack, this will likely to degrade to a simple bin packing problem. In this context if all choices are equal in terms of profit, you will likely need to focus on a different aspect of the problem which is probably something like "size." If that is the case you will want to pick the smallest item you can each time - in which case a greedy algorithm is probably sufficient and can be achieved by simply looking through your choices and choosing the smallest element.
It should be noted that a linear search can add an annoying amount of overhead to your program if its being repeated a great deal of times. Instead you may want to consider using a MIN-Heap as this will make the smallest value available at a lower computational cost.
Any ideas how to get the 5 minimum numbers from a 2D Array. I would like to know their index as well. I'm using Processing but I'm interested to find the correct way to do that.
For example: I have a 4x4 array with the following values:
3-72-64-4
12-45-9-7
86-34-81-55
31-19-18-21
I want to get the five lowest number in my Array which are 3,4,7,9,12. The problem is that I want to know their original index as well.
Example:
Array[0,0] = 3
Array[0,3] = 4
Array[1,3] = 7
Array[1,2] = 9
Is there any formula or good programming way to do that?
There is actually a very good practice that is suited for your case. It's called the 'merge sort algorithm'. It will sort your values and then you just need to output the first 5 values. Here's a link specifically for java. Have fun coding and testing it! I did :D
Well obviously you can just cycle through it and brute force with 2 for loops. Getting the original index makes it harder, as then you cant use sorts, which are faster. If it is sorted or if there is some kind of pattern, you can use a search (binary search) but from what you've given, as it looks as if the data is random, you can't really do much.
If you don't care about indexes, you can try sorts, such as merge sort mentioned by ERed or other types of sorts (I prefer quickSort). Basically you treat the 2D array as a 1D array and assume each subsequent level is just a continuation of the previous level (basically its all just one giant row broken into pieces).
I have to write a java program to simulate a robot to match lids with it's corresponding jar. The robot has two arms, one for the lids and one for the jars. I can't compare lids with lids or jars with jars. The user will enter three lines:
5(n)
9 7 2 5 6(size of lids)
2 6 5 7 9(size of jars)
The output should be:
3 5 4 2 1
The 3rd number in line 2 is equal to the 1st number in line 3 and so on.
We are supposed to use a divide and conquer algorithm and I really have no idea where to start. All I have to go by is it's similar to quicksort. Any help would be greatly appreciated.
Divide and conquer algorithms might be confusing at first. Think about it as if you have some relatively large problem that you can't solve, but if that problem was much, much smaller you could find the answer. Applying it to this situation: suppose instead of having 2 big lists of lid and jar sizes, you instead have 1 lid size and some number of jar sizes. You could easily tell me which jar that lid fits on, right? The idea of solving the problem for 1 lid is essentially breaking the large problem (several lids) into a smaller one (1 lid). Once that makes sense, you can move on the algorithm.
You will likely employ some recursion in order to write your algorithm. Start with the base case and solve the simplest meaningful problem (I like the 1 lid example). Once you can solve that problem, can you recursively solve the same problem for every lid? I'm not attaching any code because I don't want to spoil the learning experience for you (and this is clearly homework).
The whole point of "divide and conquer" is to divide up the work into multiple, smaller problems; then you solve the smaller problems and roll them up until they are combined into a solution. This pretty much implies a recursive solution.
With any recursive function, you always need a "basis case". This will be a simple case that is trivially easy to solve. For example, if you only have one jar and one lid, then you simply return that the jar matches the lid. (Because as part of the problem statement, you always have one matching lid for each jar.)
So one place to start is a trivial program that only works right for a length-1 list of jars/lids. Then add more machinery to make it more capable.
With quicksort, you choose a place to divide up the numbers (the "pivot"), then do a very rough sort (just take numbers that should be on the left of the pivot but are on the right and move them to the left, and vice versa). Then you call quicksort recursively on the sublist. Eventually each of the recursive calls to quicksort hits a basis case (a length-1 sublist); once they all have hit the basis case the quicksort is done. (Note: there are ways to optimize quicksort and make it faster by adding more code, but I'm talking about the simplest implementation of quicksort here.)
Maybe in this case you should start with a length-n list of just the numbers from 1 to n, and and then swap the numbers around until you have a correct list?
Hmm. With length-2 lists, there are only two possibilities: the lists line up, or not. If they line up you are done. If not, you swap the numbers to make them line up, and you are done. Hmm. This is similar to sorting in a way, but you can't just compare numbers directly like you can when you are sorting. (In sorting you always know that 3 sorts below 5, but here it might not be so.) So, now think about a way to break down the list and keep doing it until you have a length-2 or length-1 sublist, then handle those trivial cases.
Sounds like a fun problem. I hope you enjoy working on it.