Knapsack problem with multiple availabe packages using dynamic programming

Viewed 273

Hello and thanks for helping!
So we've got a list of fireworks containing
1) Number in stock
2) Number of fireworks in this package
3) Diameter which equals the noise and
4) The price.

This is the list:
25 17 10 21
10 15 10 18
  5 16 10 19
10 15 12 20
15   9 11 12
10   7 28 23
  8   7 16 11
10   6 16 10
25 10 18 25
25 12 18 27
10   5 40 35
60 40   5 27
  5 25 30 90
50   1 60   8

Our task is to create a shopping list and buy fireworks so we get the highest possible noise. We've got a knapsack capacity of 1000€. We're also supposed to solve this without using tables (so with dynamic programming instead).

I only use one class called Package which contains the four constraints as shown above.

At first I thought it would make sense to try to write an algorithm for a normal knapsack, so just with the price and the diameter (=weight). I tested it with a different list and it worked perfectly fine. I just iterated through all packages and then again used a nested for loop to find the best constellation (exhaustive search). My next idea was to merge the number of fireworks per package with the diameter, because fireworks can only be bought in a full package.

The only thing left which I still haven't found out is what to do with the amount of packages in stock. Like, with my current algorithm it just buys all packages of a firework until the knapsack is full. But obviously that won't be correct.

void knapsack(vector<Package*> stock){
    vector<int> indices, tmp_indices;
    int noise,tmp_noise= 0;
    int price;

    for (unsigned int i = 0; i < stock.size(); i++) {

        price = stock[i]->price;
        noise = stock[i]->diameter*stock[i]->number_fireworks; 

        indices.push_back(i);

        for (unsigned int j = 0; j < stock.size(); j++) {
            if (i != j) {

                if (price+stock[j]->price<= BUDGET) {
                    price+=stock[j]->price;
                    noise+=stock[j]->diameter*stock[j]->number_fireworks;
                    indices.push_back(j);
                }
            }

        }

        // After second loop we have a new possible constellation
        // Check if the previous constellation had a lower value and if so, set it to the current one

        if (noise > tmp_noise) {
            tmp_noise = noise;
            tmp_indices.clear();

            // tmp save
            for (auto &index : indices) {
                tmp_indices.push_back(index); 
            }

        }
        price= 0;
        noise = 0;
        indices.clear();

    }


    // Best constellation found, Print the shopping list
    cout << "\Stock.\tNum\Diameter.\Price\n" << endl;
    for(unsigned int i = 0; i < tmp_indices.size(); i++) {

        cout << stock[tmp_indices[i]]->stock<< "\t";
        cout << stock[tmp_indices[i]]->number_fireworks<< "\t";
        cout << stock[tmp_indices[i]]->diameter<< "\t";
        cout << stock[tmp_indices[i]]->price<< "\t\n";
    }

 }

We've been told that we should be able to spend exactly 1000€ to get the correct constellation of fireworks. My idea was to add another for loop to iterate through the amount of available packages, but that didn't really work...

This was our first lesson and I'm a bit desperate, because we have only learned how to solve a knapsack problem with 2 constraints and by using a table R.

Edit: Since one user insisted to get a specific question, here it is: Is the idea of using another loop to include the third constraint correct or is there a better/easier way of doing it? Or is it possible that I need a completely different approach for a knapsack with 3 instead of 2 constraints?

Thanks for help in advance

0 Answers
Related