动态编程背包K-exact项目

时间:2016-02-17 23:02:51

标签: python dynamic-programming knapsack-problem

我找到了这个非常方便的示例代码,它实现了对背包问题的DP解决方案(对发布它的人的称赞)。

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

我正在尝试修改它以包含对背包中物品数量k的约束。

我添加了第三个参数

def knapsack(items, maxweight, maxitems):

并修改重建如下:

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

如果输入足够多的项目可供选择,则总会收敛到所需的k个项目。但是,我相当确定这并未找到全局最优的最接近的近似值。我在一些搜索之后阅读的讨论是指在重建之前添加第三维k并考虑约束(我认为这将是在最佳价值评估期间)。

有人可以举例说明如何做到这一点吗?理想情况下,一个有效的python示例会非常棒,但我会选择伪代码。我已经阅读了一些使用符号的说明,但我仍然不确定如何约束k(除了我在这里所做的)。

谢谢!

1 个答案:

答案 0 :(得分:2)

正如我在上面的评论中所述,需要第三个维度,我编写了一个递归动态编程解决方案:

#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;
}

链接到ideone上的解决方案:https://ideone.com/wKzqXk