5

I found this very handy example code which implements a DP solution to the knapsack problem (kudos to the person who posted it).

https://codereview.stackexchange.com/questions/20569/dynamic-programming-solution-to-knapsack-problem

I am trying to modify it to include a constraint on the number of items k in the knapsack.

I added a third argument

def knapsack(items, maxweight, maxitems):

and modified the reconstruction as follows:

while i > 0:

    if bestvalues[i][j] != bestvalues[i - 1][j] and len(reconstruction) < maxitems:
        reconstruction.append(items[i - 1])
        j -= items[i - 1][1]

    i -= 1

Provided I input enough items to choose from this will always converge to the desired k number of items. However, I am fairly certain that this is not finding the closest approximation of the global optimum. The discussions I have read after some searching refer to adding a third dimension k and accounting for the constraint before the reconstruction (I *think this would be during the best value assessment).

Can someone provide an example of how to do this? Ideally a working python example would be fantastic but I'll settle for pseudocode. I have read a few instructions using notation but I am still not sure how to constrain with k (outside of what I have done here).

Thanks!

Community
  • 1
  • 1
elligottmc
  • 65
  • 7
  • 1
    You might get a better reception here if you post details on how this is not finding the global optimum, as well as a couple of links to the algorithms you're trying to read (even better if you post a particular algorithm and your partial implementation). As it stands, your question smells like you might be asking us to do your homework. – Prune Feb 17 '16 at 23:10
  • This is a practical problem I'm trying to solve. The use case is fantasy golf. I'm in a salaried league and the knapsack problem with k-exact items constraint is perfect for helping me select my team. I posted my implementation it's the exact same code as in the link but with the modifications I documented here. As it SMELLS to me you don't know the answer. So thanks anyway. – elligottmc Feb 17 '16 at 23:36
  • I was just letting you know what appears to turn people off on StackOverflow. I'm not the latest expert on the knapsack problem by any means. I'm trying to gather enough understanding of your situation to decide whether it's time for me to dive back into the paradigm. Thanks for the clarifications: knowing the boundaries will help. – Prune Feb 17 '16 at 23:55
  • OK fair enough, but I found the delivery insulting. Either way I don't mind I'm just trying to get my model working and hopefully gain a little understanding. This is the link I was referring to with some insight http://cs.stackexchange.com/questions/18492/variant-of-the-knapsack-problem – elligottmc Feb 18 '16 at 01:42
  • His notation for T,i,j = max{Tij-1,Tiwjj-1 + vj} maps directly to what I have in the code now. However, I'm having trouble wrapping my head around the solution I want: T,i,j,k = max{Tij-1,k, Tiwjj-1,k + vj} and putting it into code. – elligottmc Feb 18 '16 at 01:52
  • My quick rough interpretation of the notation should actually be T,i,j = max{Tij-1,Ti-wjj-1 + vj} and T,i,j,k = max{Tij-1,k, Ti-wjj-1,k + vj} I typed it incorrectly up there. Either way if you read the discussion it's clear what I'm after. – elligottmc Feb 18 '16 at 02:02
  • Thanks for the extra help on the notation. I wasn't intending to be insulting -- I was trying to guide you *away* from that area to retain people who might help. Now that I've had a little time to scan the link you sent ... *very* cool! I totally missed the factor that keeps this from being a simple backtrack. – Prune Feb 18 '16 at 02:17
  • It's all good. I'm just trying to get "to the bottom" so to speak :) – elligottmc Feb 18 '16 at 02:57
  • There should be a third dimension in the dp. – uSeemSurprised Feb 18 '16 at 10:01

1 Answers1

3

As i stated in the comment above a third dimension is required, i have written a recursive dynamic programming solution :

#include<bits/stdc++.h>

using namespace std;

int noOfItems, items[100], maxWeight, maxItems, value[100];
int dp[100][1000][100];

int solve(int idx, int currentWeight, int itemsLeft){
    if(idx == noOfItems || itemsLeft == 0) return 0;
    if(dp[idx][currentWeight][itemsLeft] != -1) return dp[idx][currentWeight][itemsLeft];
    int v1 = 0, v2 = 0;
    //try to included the current item
    if(currentWeight >= items[idx]) v1 = solve(idx+1, currentWeight-items[idx], itemsLeft-1) + value[idx];
    //exclude current item
    v2 = solve(idx+1, currentWeight, itemsLeft);
    return dp[idx][currentWeight][itemsLeft] = max(v1, v2);
}

//print the contents of the knapsack
void print(int idx, int currentWeight, int itemsLeft){
    if(idx == noOfItems || itemsLeft == 0) return;
    int v1 = 0, v2 = 0;
    if(currentWeight >= items[idx]) v1 = solve(idx+1, currentWeight-items[idx], itemsLeft-1) + value[idx];
    v2 = solve(idx+1, currentWeight, itemsLeft);
    if(v1 >= v2){
        cout << idx << " " << items[idx] << " " << value[idx] << endl;
        print(idx+1, currentWeight-items[idx], itemsLeft-1);
        return;
    }else{
        print(idx+1, currentWeight, itemsLeft);
        return;
    }
}

int main(){
    cin >> noOfItems >> maxWeight >> maxItems;
    for(int i = 0;i < noOfItems;i++) cin >> items[i] >> value[i];
    memset(dp, -1, sizeof dp);
    cout << solve(0, maxWeight, maxItems) << endl;  //prints the maximum    value that we can get from the constraints
    cout << "Printing the elements in the knapsack" << endl;
    print(0, maxWeight, maxItems);
return 0;
}

Link to solution on ideone : https://ideone.com/wKzqXk

uSeemSurprised
  • 1,826
  • 2
  • 15
  • 18